Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TGComboBox.cxx
Go to the documentation of this file.
1 // @(#)root/gui:$Id$
2 // Author: Fons Rademakers 13/01/98
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 /**************************************************************************
12 
13  This source is based on Xclass95, a Win95-looking GUI toolkit.
14  Copyright (C) 1996, 1997 David Barth, Ricky Ralston, Hector Peraza.
15 
16  Xclass95 is free software; you can redistribute it and/or
17  modify it under the terms of the GNU Library General Public
18  License as published by the Free Software Foundation; either
19  version 2 of the License, or (at your option) any later version.
20 
21 **************************************************************************/
22 
23 //////////////////////////////////////////////////////////////////////////
24 // //
25 // TGComboBox, TGComboBoxPopup //
26 // //
27 // A combobox (also known as a drop down listbox) allows the selection //
28 // of one item out of a list of items. The selected item is visible in //
29 // a little window. To view the list of possible items one has to click //
30 // on a button on the right of the little window. This will drop down //
31 // a listbox. After selecting an item from the listbox the box will //
32 // disappear and the newly selected item will be shown in the little //
33 // window. //
34 // //
35 // The TGComboBox is user callable. The TGComboBoxPopup is a service //
36 // class of the combobox. //
37 // //
38 // Selecting an item in the combobox will generate the event: //
39 // kC_COMMAND, kCM_COMBOBOX, combobox id, item id. //
40 // //
41 //////////////////////////////////////////////////////////////////////////
42 
43 #include "TGComboBox.h"
44 #include "TGScrollBar.h"
45 #include "TGPicture.h"
46 #include "TGResourcePool.h"
47 #include "Riostream.h"
48 #include "TGTextEntry.h"
49 #include "KeySymbols.h"
50 #include "RConfigure.h"
51 
52 
53 ClassImp(TGComboBoxPopup);
54 ClassImp(TGComboBox);
55 
56 ClassImp(TGLineStyleComboBox);
57 ClassImp(TGLineWidthComboBox);
58 ClassImp(TGFontTypeComboBox);
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 /// Create a combo box popup frame.
62 
63 TGComboBoxPopup::TGComboBoxPopup(const TGWindow *p, UInt_t w, UInt_t h,
64  UInt_t options, ULong_t back) :
65  TGCompositeFrame (p, w, h, options, back), fListBox(0), fSelected(0)
66 {
67  SetWindowAttributes_t wattr;
68 
69  wattr.fMask = kWAOverrideRedirect | kWASaveUnder |
70  kWABorderPixel | kWABorderWidth;
71  wattr.fOverrideRedirect = kTRUE;
72  wattr.fSaveUnder = kTRUE;
73  wattr.fBorderPixel = fgBlackPixel;
74  wattr.fBorderWidth = 1;
75  gVirtualX->ChangeWindowAttributes(fId, &wattr);
76 
77  AddInput(kStructureNotifyMask);
78  fEditDisabled = kEditDisable | kEditDisableGrab | kEditDisableBtnEnable;
79  SetWindowName();
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Handle mouse button event in combo box popup.
84 
85 Bool_t TGComboBoxPopup::HandleButton(Event_t *event)
86 {
87  if (event->fType == kButtonPress && event->fCode == kButton1) {
88  if ((fListBox != 0) && (fSelected != 0) &&
89  fListBox->GetSelectedEntry() != fSelected) {
90  // in the case the combo box popup is closed by clicking outside the
91  // list box, then select the previously selected entry
92  fListBox->Select(fSelected->EntryId());
93  }
94  EndPopup();
95  }
96  else {
97  // reset the dragging flag of the scrollbar when the button is
98  // released outside the scrollbar itself
99  fListBox->GetScrollBar()->SetDragging(kFALSE);
100  }
101  return kTRUE;
102 }
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Ungrab pointer and unmap popup window.
106 
107 void TGComboBoxPopup::EndPopup()
108 {
109  if (IsMapped()) {
110  Handle_t id = fListBox->GetContainer()->GetId();
111  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Up),
112  kAnyModifier, kFALSE);
113  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Down),
114  kAnyModifier, kFALSE);
115  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Enter),
116  kAnyModifier, kFALSE);
117  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Return),
118  kAnyModifier, kFALSE);
119  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Escape),
120  kAnyModifier, kFALSE);
121  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Space),
122  kAnyModifier, kFALSE);
123  gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
124  UnmapWindow();
125  }
126 }
127 
128 ////////////////////////////////////////////////////////////////////////////////
129 /// Popup combo box popup window at the specified place.
130 
131 void TGComboBoxPopup::PlacePopup(Int_t x, Int_t y, UInt_t w, UInt_t h)
132 {
133  Int_t rx, ry;
134  UInt_t rw, rh;
135 
136  // Parent is root window for the popup:
137  gVirtualX->GetWindowSize(fParent->GetId(), rx, ry, rw, rh);
138 
139  if (gVirtualX->InheritsFrom("TGWin32")) {
140  if ((x > 0) && ((x + abs(rx) + (Int_t)fWidth) > (Int_t)rw))
141  x = rw - abs(rx) - fWidth;
142  if ((y > 0) && (y + abs(ry) + (Int_t)fHeight > (Int_t)rh))
143  y = rh - fHeight;
144  } else {
145  if (x < 0) x = 0;
146  if (x + fWidth > rw) x = rw - fWidth;
147  if (y < 0) y = 0;
148  if (y + fHeight > rh) y = rh - fHeight;
149  }
150 
151  // remember the current selected entry
152  if (fListBox == 0) {
153  // the listbox should be the first in the list
154  TGFrameElement *el = (TGFrameElement *)fList->First();
155  fListBox = dynamic_cast<TGListBox *>(el->fFrame);
156  }
157  fSelected = fListBox ? fListBox->GetSelectedEntry() : 0;
158 
159  MoveResize(x, y, w, h);
160  MapSubwindows();
161  Layout();
162  MapRaised();
163 
164  Handle_t id = fListBox->GetContainer()->GetId();
165  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Up),
166  kAnyModifier, kTRUE);
167  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Down),
168  kAnyModifier, kTRUE);
169  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Enter),
170  kAnyModifier, kTRUE);
171  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Return),
172  kAnyModifier, kTRUE);
173  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Escape),
174  kAnyModifier, kTRUE);
175  gVirtualX->GrabKey(id, gVirtualX->KeysymToKeycode(kKey_Space),
176  kAnyModifier, kTRUE);
177  fListBox->GetContainer()->RequestFocus();
178 
179  gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
180  kPointerMotionMask, kNone,
181  fClient->GetResourcePool()->GetGrabCursor());
182 
183  if (fClient->IsEditable()) {
184  fClient->RegisterPopup(this);
185  }
186 
187  fClient->WaitForUnmap(this);
188  EndPopup();
189 }
190 
191 ////////////////////////////////////////////////////////////////////////////////
192 /// Slot handling the key press events.
193 
194 void TGComboBoxPopup::KeyPressed(TGFrame *f, UInt_t keysym, UInt_t)
195 {
196  switch ((EKeySym)keysym) {
197  case kKey_Enter:
198  case kKey_Return:
199  case kKey_Space:
200  if (fListBox && f) {
201  TGLBEntry *entry = dynamic_cast<TGLBEntry *>(f);
202  if (entry) {
203  fListBox->Select(entry->EntryId());
204  SendMessage(fListBox, MK_MSG(kC_CONTAINER, kCT_ITEMCLICK),
205  entry->EntryId(), 0);
206  }
207  }
208  EndPopup();
209  break;
210  case kKey_Escape:
211  if (fListBox)
212  ((TGContainer *)fListBox->GetContainer())->UnSelectAll();
213  EndPopup();
214  break;
215  default:
216  break;
217  }
218 }
219 
220 ////////////////////////////////////////////////////////////////////////////////
221 /// Create a combo box widget.
222 
223 TGComboBox::TGComboBox(const TGWindow *p, Int_t id, UInt_t options,
224  ULong_t back) :
225  TGCompositeFrame (p, 10, 10, options | kOwnBackground, back)
226 {
227  fWidgetId = id;
228  fMsgWindow = p;
229  fTextEntry = 0;
230 
231  fSelEntry = new TGTextLBEntry(this, new TGString(""), 0);
232  fSelEntry->ChangeOptions(fSelEntry->GetOptions() | kOwnBackground);
233 
234  AddFrame(fSelEntry, fLhs = new TGLayoutHints(kLHintsLeft |
235  kLHintsExpandY | kLHintsExpandX));
236  Init();
237 }
238 
239 ////////////////////////////////////////////////////////////////////////////////
240 /// Create an editable combo box widget.
241 
242 TGComboBox::TGComboBox(const TGWindow *p, const char *text, Int_t id,
243  UInt_t options, ULong_t back) :
244  TGCompositeFrame (p, 10, 10, options | kOwnBackground, back)
245 {
246  fWidgetId = id;
247  fMsgWindow = p;
248  fSelEntry = 0;
249 
250  fTextEntry = new TGTextEntry(this, text, id);
251  fTextEntry->SetFrameDrawn(kFALSE);
252  fTextEntry->Connect("ReturnPressed()", "TGComboBox", this, "ReturnPressed()");
253 
254  AddFrame(fTextEntry, fLhs = new TGLayoutHints(kLHintsLeft |
255  kLHintsExpandY | kLHintsExpandX));
256  Init();
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 /// Delete a combo box widget.
261 
262 TGComboBox::~TGComboBox()
263 {
264  fClient->FreePicture(fBpic);
265 
266  if (!MustCleanup()) {
267  SafeDelete(fDDButton);
268  SafeDelete(fSelEntry);
269  SafeDelete(fTextEntry);
270  SafeDelete(fLhs);
271  SafeDelete(fLhb);
272  }
273 
274  SafeDelete(fLhdd);
275  SafeDelete(fListBox);
276  if (fComboFrame) {
277  fComboFrame->EndPopup(); // force popdown in case of Qt interface
278  SafeDelete(fComboFrame);
279  }
280 }
281 
282 ////////////////////////////////////////////////////////////////////////////////
283 /// Initiate the internal classes of a combo box.
284 
285 void TGComboBox::Init()
286 {
287  fBpic = fClient->GetPicture("arrow_down.xpm");
288 
289  if (!fBpic)
290  Error("TGComboBox", "arrow_down.xpm not found");
291 
292  fDDButton = new TGScrollBarElement(this, fBpic, kDefaultScrollBarWidth,
293  kDefaultScrollBarWidth, kRaisedFrame);
294 
295  AddFrame(fDDButton, fLhb = new TGLayoutHints(kLHintsRight |
296  kLHintsExpandY));
297 
298  fComboFrame = new TGComboBoxPopup(fClient->GetDefaultRoot(), 100, 100, kVerticalFrame);
299 
300  fListBox = new TGListBox(fComboFrame, fWidgetId, kChildFrame);
301 
302  fListBox->Resize(100, 100);
303  fListBox->Associate(this);
304  fListBox->GetScrollBar()->GrabPointer(kFALSE); // combobox will do a pointergrab
305 
306  fComboFrame->AddFrame(fListBox, fLhdd = new TGLayoutHints(kLHintsExpandX |
307  kLHintsExpandY));
308  fComboFrame->SetListBox(fListBox);
309  fComboFrame->MapSubwindows();
310  fComboFrame->Resize(fComboFrame->GetDefaultSize());
311 
312  gVirtualX->GrabButton(fId, kButton1, kAnyModifier, kButtonPressMask |
313  kButtonReleaseMask | kPointerMotionMask, kNone, kNone);
314 
315  fListBox->GetContainer()->Connect("KeyPressed(TGFrame*, UInt_t, UInt_t)",
316  "TGComboBoxPopup", fComboFrame,
317  "KeyPressed(TGFrame*, UInt_t, UInt_t)");
318  // Drop down listbox of combo box should react to pointer motion
319  // so it will be able to Activate() (i.e. highlight) the different
320  // items when the mouse crosses.
321  fListBox->GetContainer()->AddInput(kButtonPressMask | kButtonReleaseMask |
322  kPointerMotionMask);
323 
324  fListBox->SetEditDisabled(kEditDisable);
325  fListBox->GetContainer()->SetEditDisabled(kEditDisable);
326  if (fSelEntry) fSelEntry->SetEditDisabled(kEditDisable | kEditDisableEvents | kEditDisableGrab);
327  if (fTextEntry) fTextEntry->SetEditDisabled(kEditDisable | kEditDisableGrab | kEditDisableBtnEnable);
328  fDDButton->SetEditDisabled(kEditDisable | kEditDisableGrab);
329  fEditDisabled = kEditDisableLayout | kEditDisableBtnEnable | kEditDisableHeight;
330 
331  SetWindowName();
332 }
333 
334 ////////////////////////////////////////////////////////////////////////////////
335 /// Draw border of combo box widget.
336 
337 void TGComboBox::DrawBorder()
338 {
339  switch (fOptions & (kSunkenFrame | kRaisedFrame | kDoubleBorder)) {
340  case kSunkenFrame | kDoubleBorder:
341  gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
342  gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
343  gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, fWidth-3, 1);
344  gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, 1, fHeight-3);
345  if (gClient->GetStyle() > 1) break;
346  gVirtualX->DrawLine(fId, GetHilightGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
347  gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
348  gVirtualX->DrawLine(fId, GetBckgndGC()(), 1, fHeight-2, fWidth-2, fHeight-2);
349  gVirtualX->DrawLine(fId, GetBckgndGC()(), fWidth-2, 1, fWidth-2, fHeight-2);
350  break;
351 
352  default:
353  TGCompositeFrame::DrawBorder();
354  break;
355  }
356 }
357 
358 ////////////////////////////////////////////////////////////////////////////////
359 /// Switch text input or readonly mode of combobox (not perfect yet).
360 
361 void TGComboBox::EnableTextInput(Bool_t on)
362 {
363  // UInt_t w, h;
364  const char *text = "";
365  Pixel_t back = TGFrame::GetWhitePixel(); // default
366 
367  if (on) {
368  if (fSelEntry) {
369  back = fSelEntry->GetBackground();
370  text = ((TGTextLBEntry*)fSelEntry)->GetText()->GetString();
371  if (fTextEntry && fSelEntry->InheritsFrom(TGTextLBEntry::Class())) {
372  fTextEntry->SetText(text);
373  }
374  RemoveFrame(fSelEntry);
375  //w = fSelEntry->GetWidth();
376  //h = fSelEntry->GetHeight();
377  fSelEntry->DestroyWindow();
378  delete fSelEntry;
379  fSelEntry = 0;
380  }
381  if (!fTextEntry) {
382  fTextEntry = new TGTextEntry(this, text, 0);
383  fTextEntry->SetFrameDrawn(kFALSE);
384  fTextEntry->Connect("ReturnPressed()", "TGComboBox", this, "ReturnPressed()");
385  AddFrame(fTextEntry, fLhs);
386  fTextEntry->SetEditDisabled(kEditDisable | kEditDisableGrab | kEditDisableBtnEnable);
387  }
388  fTextEntry->SetBackgroundColor(back);
389  MapSubwindows();
390  // coverity[returned_null]
391  // coverity[dereference]
392  GetLayoutManager()->Layout();
393  } else {
394  if (fTextEntry) {
395  back = fTextEntry->GetBackground();
396  text = fTextEntry->GetText();
397  RemoveFrame(fTextEntry);
398  fTextEntry->DestroyWindow();
399  //w = fTextEntry->GetWidth();
400  //h = fTextEntry->GetHeight();
401  delete fTextEntry;
402  fTextEntry = 0;
403  }
404  if (!fSelEntry) {
405  fSelEntry = new TGTextLBEntry(this, new TGString(text), 0);
406  fSelEntry->ChangeOptions(fSelEntry->GetOptions() | kOwnBackground);
407  AddFrame(fSelEntry, fLhs);
408  fSelEntry->SetEditDisabled(kEditDisable | kEditDisableGrab);
409  }
410  fSelEntry->SetBackgroundColor(back);
411  MapSubwindows();
412  // coverity[returned_null]
413  // coverity[dereference]
414  GetLayoutManager()->Layout();
415  }
416 }
417 
418 ////////////////////////////////////////////////////////////////////////////////
419 /// Find entry by name.
420 
421 TGLBEntry *TGComboBox::FindEntry(const char *s) const
422 {
423  TGLBEntry *sel = 0;
424  sel = fListBox->FindEntry(s);
425  return sel;
426 }
427 
428 ////////////////////////////////////////////////////////////////////////////////
429 /// Set a new combo box value (normally update of text string in
430 /// fSelEntry is done via fSelEntry::Update()).
431 
432 void TGComboBox::SetTopEntry(TGLBEntry *e, TGLayoutHints *lh)
433 {
434  if (!fSelEntry) return;
435 
436  RemoveFrame(fSelEntry);
437  fSelEntry->DestroyWindow();
438  delete fSelEntry;
439  delete fLhs;
440  fSelEntry = e;
441  fLhs = lh;
442  AddFrame(fSelEntry, fLhs);
443  Layout();
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 /// Make the selected item visible in the combo box window
448 /// and emit signals according to the second parameter.
449 
450 void TGComboBox::Select(Int_t id, Bool_t emit)
451 {
452  if (id!=GetSelected()) {
453  TGLBEntry *e;
454  e = fListBox->Select(id);
455  if (e) {
456  if (fSelEntry) {
457  fSelEntry->Update(e);
458  Layout();
459  } else if (fTextEntry && e->InheritsFrom(TGTextLBEntry::Class())) {
460  TGTextLBEntry *te = (TGTextLBEntry*)e;
461  fTextEntry->SetText(te->GetText()->GetString());
462  }
463  if (emit) {
464  Selected(fWidgetId, id);
465  Selected(id);
466  }
467  }
468  }
469 }
470 
471 ////////////////////////////////////////////////////////////////////////////////
472 /// Handle mouse button events in the combo box.
473 
474 Bool_t TGComboBox::HandleButton(Event_t *event)
475 {
476  if (!fDDButton || !fDDButton->IsEnabled()) return kFALSE;
477 
478  if (event->fType == kButtonPress) {
479  Window_t child = (Window_t)event->fUser[0]; // fUser[0] = child window
480 
481  if (child == fDDButton->GetId() || (fSelEntry && child == fSelEntry->GetId())) {
482  fDDButton->SetState(kButtonDown);
483 
484  if (fTextEntry && (child == fTextEntry->GetId())) {
485  return fTextEntry->HandleButton(event);
486  }
487  int ax, ay;
488  Window_t wdummy;
489  gVirtualX->TranslateCoordinates(fId, fComboFrame->GetParent()->GetId(),
490  0, fHeight, ax, ay, wdummy);
491  // Drop down listbox of combo box should react to pointer motion...
492  fListBox->GetContainer()->AddInput(kPointerMotionMask);
493 #ifdef R__HAS_COCOA
494  gVirtualX->SetWMTransientHint(fComboFrame->GetId(), GetId());
495 #endif
496  fComboFrame->PlacePopup(ax, ay, fWidth-2, fComboFrame->GetDefaultHeight());
497  fDDButton->SetState(kButtonUp);
498 #ifdef R__HAS_COCOA
499  //tp: I need this modification - "button" is not repainted correctly
500  //with Cocoa, when combobox is closed (reason is quite complex), happens
501  //when item is wider than combobox.
502  //TODO: find another way :)
503  fClient->NeedRedraw(fDDButton);
504 #endif
505  } else if (fTextEntry) {
506  return fTextEntry->HandleButton(event);
507  }
508  }
509  return kTRUE;
510 }
511 
512 ////////////////////////////////////////////////////////////////////////////////
513 /// Remove entry. If id == -1, the currently selected entry is removed
514 
515 void TGComboBox::RemoveEntry(Int_t id)
516 {
517  fListBox->RemoveEntry(id);
518 
519  if (id < 0) {
520  if (fSelEntry) {
521  ((TGTextLBEntry*)fSelEntry)->SetTitle("");
522  fClient->NeedRedraw(fSelEntry);
523  } else {
524  fTextEntry->SetTitle("");
525  fClient->NeedRedraw(fTextEntry);
526  }
527  }
528  Resize();
529 }
530 
531 ////////////////////////////////////////////////////////////////////////////////
532 /// layout combobox
533 
534 void TGComboBox::Layout()
535 {
536  TGCompositeFrame::Layout();
537  UInt_t h = fListBox->GetNumberOfEntries()*fListBox->GetItemVsize();
538 
539  if (h && (h < 100)) {
540  fListBox->Resize(fListBox->GetWidth(), h);
541  }
542 }
543 
544 ////////////////////////////////////////////////////////////////////////////////
545 /// Handle double click in text entry.
546 
547 Bool_t TGComboBox::HandleDoubleClick(Event_t *event)
548 {
549  return fTextEntry ? fTextEntry->HandleDoubleClick(event) : kTRUE;
550 }
551 
552 ////////////////////////////////////////////////////////////////////////////////
553 /// Handle pointer motion in text entry.
554 
555 Bool_t TGComboBox::HandleMotion(Event_t *event)
556 {
557  return fTextEntry ? fTextEntry->HandleMotion(event) : kTRUE;
558 }
559 
560 ////////////////////////////////////////////////////////////////////////////////
561 /// Handle selection in text entry.
562 
563 Bool_t TGComboBox::HandleSelection(Event_t *event)
564 {
565  return fTextEntry ? fTextEntry->HandleSelection(event) : kTRUE;
566 }
567 
568 ////////////////////////////////////////////////////////////////////////////////
569 /// Handle selection request in text entry.
570 
571 Bool_t TGComboBox::HandleSelectionRequest(Event_t *event)
572 {
573  return fTextEntry ? fTextEntry->HandleSelectionRequest(event) : kTRUE;
574 }
575 
576 ////////////////////////////////////////////////////////////////////////////////
577 /// Process messages generated by the listbox and forward
578 /// messages to the combobox message handling window. Parm2 contains
579 /// the id of the selected listbox entry.
580 
581 Bool_t TGComboBox::ProcessMessage(Long_t msg, Long_t, Long_t parm2)
582 {
583  TGLBEntry *e;
584 
585  switch (GET_MSG(msg)) {
586  case kC_COMMAND:
587  switch (GET_SUBMSG(msg)) {
588  case kCM_LISTBOX:
589  e = fListBox->GetSelectedEntry();
590  if (fSelEntry) {
591  fSelEntry->Update(e);
592  } else if (fTextEntry &&
593  e->InheritsFrom(TGTextLBEntry::Class())) {
594  TGTextLBEntry *te = (TGTextLBEntry*)e;
595  fTextEntry->SetText(te->GetText()->GetString());
596  }
597  // coverity[returned_null]
598  // coverity[dereference]
599  GetLayoutManager()->Layout();
600  fComboFrame->EndPopup();
601  fDDButton->SetState(kButtonUp);
602  SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_COMBOBOX),
603  fWidgetId, parm2);
604  if (e->InheritsFrom(TGTextLBEntry::Class())) {
605  const char *text;
606  text = ((TGTextLBEntry*)e)->GetText()->GetString();
607  Selected(text);
608  }
609  Selected(fWidgetId, (Int_t)parm2);
610  Selected((Int_t)parm2);
611  fClient->NeedRedraw(this);
612  break;
613  }
614  break;
615 
616  default:
617  break;
618  }
619  return kTRUE;
620 }
621 
622 ////////////////////////////////////////////////////////////////////////////////
623 /// Emit signal.
624 
625 void TGComboBox::Selected(Int_t widgetId, Int_t id)
626 {
627  Long_t args[2];
628 
629  args[0] = widgetId;
630  args[1] = id;
631 
632  Emit("Selected(Int_t,Int_t)", args);
633 }
634 
635 ////////////////////////////////////////////////////////////////////////////////
636 /// Set state of combo box. If kTRUE=enabled, kFALSE=disabled.
637 
638 void TGComboBox::SetEnabled(Bool_t on)
639 {
640  fDDButton->SetEnabled(on);
641  if (on) {
642  SetFlags(kWidgetIsEnabled);
643  fSelEntry->SetBackgroundColor(GetBackground());
644  } else {
645  ClearFlags(kWidgetIsEnabled);
646  fSelEntry->SetBackgroundColor(GetDefaultFrameBackground());
647  }
648  fClient->NeedRedraw(fSelEntry);
649 }
650 
651 ////////////////////////////////////////////////////////////////////////////////
652 /// Add new entry to combo box when return key pressed inside text entry
653 /// ReturnPressed signal is emitted.
654 
655 void TGComboBox::ReturnPressed()
656 {
657  if (!fTextEntry) return;
658 
659  TGLBContainer *lbc = (TGLBContainer *)fListBox->GetContainer();
660  TString text = fTextEntry->GetText();
661 
662  TIter next(lbc->GetList());
663  TGFrameElement *el;
664 
665  Emit("ReturnPressed()");
666 
667  while ((el = (TGFrameElement *)next())) {
668  TGTextLBEntry *lbe = (TGTextLBEntry *)el->fFrame;
669  if (lbe->GetText()->GetString() == text) {
670  return;
671  }
672  }
673 
674  Int_t nn = GetNumberOfEntries() + 1;
675  AddEntry(text.Data(), nn);
676  Select(nn);
677 }
678 
679 ////////////////////////////////////////////////////////////////////////////////
680 /// Remove all entries from combo box.
681 
682 void TGComboBox::RemoveAll()
683 {
684  fListBox->RemoveAll();
685 
686  if (fSelEntry) {
687  ((TGTextLBEntry*)fSelEntry)->SetTitle("");
688  fClient->NeedRedraw(fSelEntry);
689  } else {
690  fTextEntry->SetTitle("");
691  fClient->NeedRedraw(fTextEntry);
692  }
693 }
694 
695 ////////////////////////////////////////////////////////////////////////////////
696 /// Save a combo box widget as a C++ statement(s) on output stream out.
697 
698 void TGComboBox::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
699 {
700  if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
701 
702  out << std::endl << " // combo box" << std::endl;
703  out << " TGComboBox *";
704 
705  if (!fTextEntry) {
706  out << GetName() << " = new TGComboBox(" << fParent->GetName() << "," << fWidgetId;
707  } else {
708  out << GetName() << " = new TGComboBox(" << fParent->GetName() << ",";
709  out << '\"' << fTextEntry->GetText() << '\"' << "," <<fWidgetId;
710  }
711 
712  if (fBackground == GetWhitePixel()) {
713  if (GetOptions() == (kHorizontalFrame | kSunkenFrame | kDoubleBorder)) {
714  out <<");" << std::endl;
715  } else {
716  out << "," << GetOptionString() << ");" << std::endl;
717  }
718  } else {
719  out << "," << GetOptionString() << ",ucolor);" << std::endl;
720  }
721  if (option && strstr(option, "keep_names"))
722  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
723 
724  TGTextLBEntry *b;
725  TGFrameElement *el;
726  TGListBox *lb = GetListBox();
727 
728  TIter next(((TGLBContainer *)lb->GetContainer())->GetList());
729 
730  while ((el = (TGFrameElement *) next())) {
731  b = (TGTextLBEntry *) el->fFrame;
732  out << " " << GetName() << "->AddEntry(";
733  b->SavePrimitive(out, option);
734  out << ");" << std::endl;
735  }
736 
737  out << " " << GetName() << "->Resize(" << GetWidth() << ","
738  << GetHeight() << ");" << std::endl;
739  out << " " << GetName() << "->Select(" << GetSelected() << ");" << std::endl;
740 }
741 
742 ////////////////////////////////////////////////////////////////////////////////
743 /// Create a line style combo box.
744 
745 TGLineStyleComboBox::TGLineStyleComboBox(const TGWindow *p, Int_t id,
746  UInt_t options, Pixel_t back)
747  : TGComboBox(p, id, options, back)
748 {
749  SetTopEntry(new TGLineLBEntry(this, 0),
750  new TGLayoutHints(kLHintsLeft | kLHintsExpandY | kLHintsExpandX));
751  fSelEntry->ChangeOptions(fSelEntry->GetOptions() | kOwnBackground);
752 
753  for (Int_t i = 1; i <= 10; i++)
754  AddEntry(new TGLineLBEntry(GetListBox()->GetContainer(), i,
755  TString::Format("%d",i), 0, i),
756  new TGLayoutHints(kLHintsTop | kLHintsExpandX));
757 
758  Select(1, kFALSE); // to have first entry selected
759 
760  SetWindowName();
761 }
762 
763 ////////////////////////////////////////////////////////////////////////////////
764 /// Save a line style combo box widget as a C++ statement(s).
765 
766 void TGLineStyleComboBox::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
767 {
768  out << std::endl << " // line style combo box" << std::endl;
769  out << " TGLineStyleComboBox *";
770 
771  out << GetName() << " = new TGLineStyleComboBox(" << fParent->GetName()
772  << "," << fWidgetId << ");" << std::endl;
773  if (option && strstr(option, "keep_names"))
774  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
775  out << " " << GetName() << "->Resize(" << GetWidth() << ","
776  << GetHeight() << ");" << std::endl;
777  out << " " << GetName() << "->Select(" << GetSelected() << ");" << std::endl;
778 }
779 
780 ////////////////////////////////////////////////////////////////////////////////
781 /// Create a line width combo box.
782 /// If "none" is equal to kTRUE the first entry is "None".
783 
784 TGLineWidthComboBox::TGLineWidthComboBox(const TGWindow *p, Int_t id,
785  UInt_t options, Pixel_t back, Bool_t none)
786  : TGComboBox(p, id, options, back)
787 {
788  SetTopEntry(new TGLineLBEntry(this,0),
789  new TGLayoutHints(kLHintsLeft | kLHintsExpandY | kLHintsExpandX));
790  fSelEntry->ChangeOptions(fSelEntry->GetOptions() | kOwnBackground);
791 
792  if (none) {
793  AddEntry(new TGLineLBEntry(GetListBox()->GetContainer(), 0, "None", 0, 0),
794  new TGLayoutHints(kLHintsTop | kLHintsExpandX));
795  }
796 
797  for (Int_t i = 0; i < 16; i++)
798  AddEntry(new TGLineLBEntry(GetListBox()->GetContainer(), i,
799  TString::Format("%d",i), i, 0),
800  new TGLayoutHints(kLHintsTop | kLHintsExpandX));
801  Select(1, kFALSE); // to have first entry selected
802  SetWindowName();
803 }
804 
805 ////////////////////////////////////////////////////////////////////////////////
806 /// Save a line width combo box widget as a C++ statement(s).
807 
808 void TGLineWidthComboBox::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
809 {
810  out << std::endl << " // line width combo box" << std::endl;
811  out << " TGLineWidthComboBox *";
812 
813  out << GetName() << " = new TGLineWidthComboBox(" << fParent->GetName()
814  << "," << fWidgetId << ");" << std::endl;
815  if (option && strstr(option, "keep_names"))
816  out << " " << GetName() << "->SetName(\"" << GetName() << "\");" << std::endl;
817  out << " " << GetName() << "->Resize(" << GetWidth() << ","
818  << GetHeight() << ");" << std::endl;
819  out << " " << GetName() << "->Select(" << GetSelected() << ");" << std::endl;
820 }
821 
822 static const char *gFonts[][2] = { // unix name, name
823  { "", "" }, //not used
824  { "-*-times-medium-i-*-*-12-*-*-*-*-*-*-*", "1. times italic" },
825  { "-*-times-bold-r-*-*-12-*-*-*-*-*-*-*", "2. times bold" },
826  { "-*-times-bold-i-*-*-12-*-*-*-*-*-*-*", "3. times bold italic" },
827  { "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", "4. helvetica" },
828  { "-*-helvetica-medium-o-*-*-12-*-*-*-*-*-*-*", "5. helvetica italic" },
829  { "-*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*", "6. helvetica bold" },
830  { "-*-helvetica-bold-o-*-*-12-*-*-*-*-*-*-*", "7. helvetica bold italic" },
831  { "-*-courier-medium-r-*-*-12-*-*-*-*-*-*-*", "8. courier" },
832  { "-*-courier-medium-o-*-*-12-*-*-*-*-*-*-*", "9. courier italic" },
833  { "-*-courier-bold-r-*-*-12-*-*-*-*-*-*-*", "10. courier bold" },
834  { "-*-courier-bold-o-*-*-12-*-*-*-*-*-*-*", "11. courier bold italic" },
835  { "-*-symbol-medium-r-*-*-12-*-*-*-*-*-*-*", "12. symbol" },
836  { "-*-times-medium-r-*-*-12-*-*-*-*-*-*-*", "13. times" },
837  { 0, 0}
838 };
839 
840 ////////////////////////////////////////////////////////////////////////////////
841 /// Create a text font combo box.
842 
843 TGFontTypeComboBox::TGFontTypeComboBox(const TGWindow *p, Int_t id,
844  UInt_t options, Pixel_t back) :
845  TGComboBox(p, id, options, back)
846 {
847  Int_t noFonts = 0;
848 
849  for (Int_t i = 1; gFonts[i][0] != 0 && noFonts < kMaxFonts; i++) {
850 
851  fFonts[noFonts] = gVirtualX->LoadQueryFont(gFonts[i][0]);
852 
853  if (fFonts[noFonts] == 0)
854  fFonts[noFonts] = TGTextLBEntry::GetDefaultFontStruct();
855 
856  GCValues_t gval;
857  gval.fMask = kGCFont;
858  gval.fFont = gVirtualX->GetFontHandle(fFonts[noFonts]);
859 
860  AddEntry(new TGTextLBEntry(GetListBox()->GetContainer(),
861  new TGString(gFonts[i][1]), i,
862  fClient->GetGC(&gval, kTRUE)->GetGC(), fFonts[noFonts]),
863  new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX));
864  noFonts++;
865  }
866 
867  if (noFonts < kMaxFonts - 1)
868  fFonts[noFonts] = 0;
869 
870  Select(1, kFALSE); // to have first entry selected
871  SetWindowName();
872 }
873 
874 ////////////////////////////////////////////////////////////////////////////////
875 /// Text font combo box dtor.
876 
877 TGFontTypeComboBox::~TGFontTypeComboBox()
878 {
879  for (int i = 0; i < kMaxFonts && fFonts[i] != 0; i++) {
880  if (fFonts[i] != TGTextLBEntry::GetDefaultFontStruct()) gVirtualX->DeleteFont(fFonts[i]);
881  }
882 }