#include "TGComboBox.h"
#include "TGScrollBar.h"
#include "TGPicture.h"
#include "TGResourcePool.h"
#include "Riostream.h"
#include "TGTextEntry.h"
ClassImp(TGComboBoxPopup)
ClassImp(TGComboBox)
ClassImp(TGLineStyleComboBox)
ClassImp(TGLineWidthComboBox)
ClassImp(TGFontTypeComboBox)
TGComboBoxPopup::TGComboBoxPopup(const TGWindow *p, UInt_t w, UInt_t h,
UInt_t options, ULong_t back) :
TGCompositeFrame (p, w, h, options, back)
{
SetWindowAttributes_t wattr;
wattr.fMask = kWAOverrideRedirect | kWASaveUnder |
kWABorderPixel | kWABorderWidth;
wattr.fOverrideRedirect = kTRUE;
wattr.fSaveUnder = kTRUE;
wattr.fBorderPixel = fgBlackPixel;
wattr.fBorderWidth = 1;
gVirtualX->ChangeWindowAttributes(fId, &wattr);
AddInput(kStructureNotifyMask);
fEditDisabled = kEditDisable | kEditDisableGrab | kEditDisableBtnEnable;
SetWindowName();
}
Bool_t TGComboBoxPopup::HandleButton(Event_t *event)
{
if (event->fType == kButtonPress && event->fCode == kButton1)
EndPopup();
return kTRUE;
}
void TGComboBoxPopup::EndPopup()
{
if (IsMapped()) {
gVirtualX->GrabPointer(0, 0, 0, 0, kFALSE);
UnmapWindow();
}
}
void TGComboBoxPopup::PlacePopup(Int_t x, Int_t y, UInt_t w, UInt_t h)
{
Int_t rx, ry;
UInt_t rw, rh;
gVirtualX->GetWindowSize(fParent->GetId(), rx, ry, rw, rh);
if (x < 0) x = 0;
if (x + fWidth > rw) x = rw - fWidth;
if (y < 0) y = 0;
if (y + fHeight > rh) y = rh - fHeight;
MoveResize(x, y, w, h);
MapSubwindows();
Layout();
MapRaised();
gVirtualX->GrabPointer(fId, kButtonPressMask | kButtonReleaseMask |
kPointerMotionMask, kNone,
fClient->GetResourcePool()->GetGrabCursor());
if (fClient->IsEditable()) {
fClient->RegisterPopup(this);
}
fClient->WaitForUnmap(this);
EndPopup();
}
TGComboBox::TGComboBox(const TGWindow *p, Int_t id, UInt_t options,
ULong_t back) :
TGCompositeFrame (p, 10, 10, options | kOwnBackground, back)
{
fWidgetId = id;
fMsgWindow = p;
fTextEntry = 0;
fSelEntry = new TGTextLBEntry(this, new TGString(""), 0);
fSelEntry->ChangeOptions(fSelEntry->GetOptions() | kOwnBackground);
AddFrame(fSelEntry, fLhs = new TGLayoutHints(kLHintsLeft |
kLHintsExpandY | kLHintsExpandX));
Init();
}
TGComboBox::TGComboBox(const TGWindow *p, const char *text, Int_t id,
UInt_t options, ULong_t back) :
TGCompositeFrame (p, 10, 10, options | kOwnBackground, back)
{
fWidgetId = id;
fMsgWindow = p;
fSelEntry = 0;
fTextEntry = new TGTextEntry(this, text, id);
fTextEntry->SetFrameDrawn(kFALSE);
fTextEntry->Connect("ReturnPressed()", "TGComboBox", this, "ReturnPressed()");
AddFrame(fTextEntry, fLhs = new TGLayoutHints(kLHintsLeft |
kLHintsExpandY | kLHintsExpandX));
Init();
}
TGComboBox::~TGComboBox()
{
fClient->FreePicture(fBpic);
if (!MustCleanup()) {
SafeDelete(fDDButton);
SafeDelete(fSelEntry);
SafeDelete(fTextEntry);
SafeDelete(fLhs);
SafeDelete(fLhb);
}
SafeDelete(fLhdd);
SafeDelete(fListBox);
if (fComboFrame) {
fComboFrame->EndPopup();
SafeDelete(fComboFrame);
}
}
void TGComboBox::Init()
{
fBpic = fClient->GetPicture("arrow_down.xpm");
if (!fBpic)
Error("TGComboBox", "arrow_down.xpm not found");
fDDButton = new TGScrollBarElement(this, fBpic, kDefaultScrollBarWidth,
kDefaultScrollBarWidth, kRaisedFrame);
AddFrame(fDDButton, fLhb = new TGLayoutHints(kLHintsRight |
kLHintsExpandY));
fComboFrame = new TGComboBoxPopup(fClient->GetDefaultRoot(), 100, 100, kVerticalFrame);
fListBox = new TGListBox(fComboFrame, fWidgetId, kChildFrame);
fListBox->Resize(100, 100);
fListBox->Associate(this);
fListBox->GetScrollBar()->GrabPointer(kFALSE);
fComboFrame->AddFrame(fListBox, fLhdd = new TGLayoutHints(kLHintsExpandX |
kLHintsExpandY));
fComboFrame->MapSubwindows();
fComboFrame->Resize(fComboFrame->GetDefaultSize());
gVirtualX->GrabButton(fId, kButton1, kAnyModifier, kButtonPressMask |
kButtonReleaseMask | kPointerMotionMask, kNone, kNone);
fListBox->GetContainer()->AddInput(kButtonPressMask | kButtonReleaseMask |
kPointerMotionMask);
fListBox->SetEditDisabled(kEditDisable);
fListBox->GetContainer()->SetEditDisabled(kEditDisable);
if (fSelEntry) fSelEntry->SetEditDisabled(kEditDisable | kEditDisableEvents | kEditDisableGrab);
if (fTextEntry) fTextEntry->SetEditDisabled(kEditDisable | kEditDisableGrab | kEditDisableBtnEnable);
fDDButton->SetEditDisabled(kEditDisable | kEditDisableGrab);
fEditDisabled = kEditDisableLayout | kEditDisableBtnEnable | kEditDisableHeight;
SetWindowName();
}
void TGComboBox::DrawBorder()
{
switch (fOptions & (kSunkenFrame | kRaisedFrame | kDoubleBorder)) {
case kSunkenFrame | kDoubleBorder:
gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, fWidth-2, 0);
gVirtualX->DrawLine(fId, GetShadowGC()(), 0, 0, 0, fHeight-2);
gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, fWidth-3, 1);
gVirtualX->DrawLine(fId, GetBlackGC()(), 1, 1, 1, fHeight-3);
gVirtualX->DrawLine(fId, GetHilightGC()(), 0, fHeight-1, fWidth-1, fHeight-1);
gVirtualX->DrawLine(fId, GetHilightGC()(), fWidth-1, fHeight-1, fWidth-1, 0);
gVirtualX->DrawLine(fId, GetBckgndGC()(), 1, fHeight-2, fWidth-2, fHeight-2);
gVirtualX->DrawLine(fId, GetBckgndGC()(), fWidth-2, 1, fWidth-2, fHeight-2);
break;
default:
TGCompositeFrame::DrawBorder();
break;
}
}
void TGComboBox::EnableTextInput(Bool_t on)
{
UInt_t w, h;
const char *text = "";
Pixel_t back = TGFrame::GetWhitePixel();
if (on) {
if (fSelEntry) {
back = fSelEntry->GetBackground();
text = ((TGTextLBEntry*)fSelEntry)->GetText()->GetString();
if (fTextEntry && fSelEntry->InheritsFrom(TGTextLBEntry::Class())) {
fTextEntry->SetText(text);
}
RemoveFrame(fSelEntry);
w = fSelEntry->GetWidth();
h = fSelEntry->GetHeight();
fSelEntry->DestroyWindow();
delete fSelEntry;
fSelEntry = 0;
}
if (!fTextEntry) {
fTextEntry = new TGTextEntry(this, text, 0);
fTextEntry->SetFrameDrawn(kFALSE);
fTextEntry->Connect("ReturnPressed()", "TGComboBox", this, "ReturnPressed()");
AddFrame(fTextEntry, fLhs);
fTextEntry->SetEditDisabled(kEditDisable | kEditDisableGrab | kEditDisableBtnEnable);
}
fTextEntry->SetBackgroundColor(back);
MapSubwindows();
GetLayoutManager()->Layout();
} else {
if (fTextEntry) {
back = fTextEntry->GetBackground();
text = fTextEntry->GetText();
RemoveFrame(fTextEntry);
fTextEntry->DestroyWindow();
w = fTextEntry->GetWidth();
h = fTextEntry->GetHeight();
delete fTextEntry;
fTextEntry = 0;
}
if (!fSelEntry) {
fSelEntry = new TGTextLBEntry(this, new TGString(text), 0);
fSelEntry->ChangeOptions(fSelEntry->GetOptions() | kOwnBackground);
AddFrame(fSelEntry, fLhs);
fSelEntry->SetEditDisabled(kEditDisable | kEditDisableGrab);
}
fSelEntry->SetBackgroundColor(back);
MapSubwindows();
GetLayoutManager()->Layout();
}
}
TGLBEntry *TGComboBox::FindEntry(const char *s) const
{
TGLBEntry *sel = 0;
sel = fListBox->FindEntry(s);
return sel;
}
void TGComboBox::SetTopEntry(TGLBEntry *e, TGLayoutHints *lh)
{
if (!fSelEntry) return;
RemoveFrame(fSelEntry);
fSelEntry->DestroyWindow();
delete fSelEntry;
delete fLhs;
fSelEntry = e;
fLhs = lh;
AddFrame(fSelEntry, fLhs);
Layout();
}
void TGComboBox::Select(Int_t id, Bool_t emit)
{
if (id!=GetSelected()) {
TGLBEntry *e;
e = fListBox->Select(id);
if (e) {
if (fSelEntry) {
fSelEntry->Update(e);
Layout();
if (emit) {
Selected(fWidgetId, id);
Selected(id);
}
}
}
}
}
Bool_t TGComboBox::HandleButton(Event_t *event)
{
if (!fDDButton || !fDDButton->IsEnabled()) return kFALSE;
if (event->fType == kButtonPress) {
Window_t child = (Window_t)event->fUser[0];
if (child == fDDButton->GetId() || (fSelEntry && child == fSelEntry->GetId())) {
fDDButton->SetState(kButtonDown);
if (fTextEntry && (child == fTextEntry->GetId())) {
return fTextEntry->HandleButton(event);
}
int ax, ay;
Window_t wdummy;
gVirtualX->TranslateCoordinates(fId, fComboFrame->GetParent()->GetId(),
0, fHeight, ax, ay, wdummy);
fListBox->GetContainer()->AddInput(kPointerMotionMask);
fComboFrame->PlacePopup(ax, ay, fWidth-2, fComboFrame->GetDefaultHeight());
fDDButton->SetState(kButtonUp);
} else if (fTextEntry) {
return fTextEntry->HandleButton(event);
}
}
return kTRUE;
}
void TGComboBox::RemoveEntry(Int_t id)
{
fListBox->RemoveEntry(id);
if (id < 0) {
if (fSelEntry) {
((TGTextLBEntry*)fSelEntry)->SetTitle("");
fClient->NeedRedraw(fSelEntry);
} else {
fTextEntry->SetTitle("");
fClient->NeedRedraw(fTextEntry);
}
}
Resize();
}
void TGComboBox::Layout()
{
TGCompositeFrame::Layout();
UInt_t h = fListBox->GetNumberOfEntries()*fListBox->GetItemVsize();
if (h && (h < 100)) {
fListBox->Resize(fListBox->GetWidth(), h);
}
}
Bool_t TGComboBox::HandleDoubleClick(Event_t *event)
{
return fTextEntry ? fTextEntry->HandleDoubleClick(event) : kTRUE;
}
Bool_t TGComboBox::HandleMotion(Event_t *event)
{
return fTextEntry ? fTextEntry->HandleMotion(event) : kTRUE;
}
Bool_t TGComboBox::HandleSelection(Event_t *event)
{
return fTextEntry ? fTextEntry->HandleSelection(event) : kTRUE;
}
Bool_t TGComboBox::HandleSelectionRequest(Event_t *event)
{
return fTextEntry ? fTextEntry->HandleSelectionRequest(event) : kTRUE;
}
Bool_t TGComboBox::ProcessMessage(Long_t msg, Long_t, Long_t parm2)
{
TGLBEntry *e;
switch (GET_MSG(msg)) {
case kC_COMMAND:
switch (GET_SUBMSG(msg)) {
case kCM_LISTBOX:
e = fListBox->GetSelectedEntry();
if (fSelEntry) {
fSelEntry->Update(e);
} else if (fTextEntry &&
e->InheritsFrom(TGTextLBEntry::Class())) {
TGTextLBEntry *te = (TGTextLBEntry*)e;
fTextEntry->SetText(te->GetText()->GetString());
}
GetLayoutManager()->Layout();
fComboFrame->EndPopup();
fDDButton->SetState(kButtonUp);
SendMessage(fMsgWindow, MK_MSG(kC_COMMAND, kCM_COMBOBOX),
fWidgetId, parm2);
if (e->InheritsFrom(TGTextLBEntry::Class())) {
const char *text;
text = ((TGTextLBEntry*)e)->GetText()->GetString();
Selected(text);
}
Selected(fWidgetId, (Int_t)parm2);
Selected((Int_t)parm2);
fClient->NeedRedraw(this);
break;
}
break;
default:
break;
}
return kTRUE;
}
void TGComboBox::Selected(Int_t widgetId, Int_t id)
{
Long_t args[2];
args[0] = widgetId;
args[1] = id;
Emit("Selected(Int_t,Int_t)", args);
}
void TGComboBox::SetEnabled(Bool_t on)
{
fDDButton->SetEnabled(on);
if (on) {
SetFlags(kWidgetIsEnabled);
fSelEntry->SetBackgroundColor(GetBackground());
} else {
ClearFlags(kWidgetIsEnabled);
fSelEntry->SetBackgroundColor(GetDefaultFrameBackground());
}
fClient->NeedRedraw(fSelEntry);
}
void TGComboBox::ReturnPressed()
{
if (!fTextEntry) return;
TGLBContainer *lbc = (TGLBContainer *)fListBox->GetContainer();
TString text = fTextEntry->GetText();
TIter next(lbc->GetList());
TGFrameElement *el;
Emit("ReturnPressed()");
while ((el = (TGFrameElement *)next())) {
TGTextLBEntry *lbe = (TGTextLBEntry *)el->fFrame;
if (lbe->GetText()->GetString() == text) {
return;
}
}
Int_t nn = GetNumberOfEntries() + 1;
AddEntry(text.Data(), nn);
Select(nn);
}
void TGComboBox::RemoveAll()
{
fListBox->RemoveAll();
if (fSelEntry) {
((TGTextLBEntry*)fSelEntry)->SetTitle("");
fClient->NeedRedraw(fSelEntry);
} else {
fTextEntry->SetTitle("");
fClient->NeedRedraw(fTextEntry);
}
}
void TGComboBox::SavePrimitive(ostream &out, Option_t *option )
{
if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);
out << endl << " // combo box" << endl;
out << " TGComboBox *";
if (!fTextEntry) {
out << GetName() << " = new TGComboBox(" << fParent->GetName() << "," << fWidgetId;
} else {
out << GetName() << " = new TGComboBox(" << fParent->GetName() << ",";
out << '\"' << fTextEntry->GetText() << '\"' << "," <<fWidgetId;
}
if (fBackground == GetWhitePixel()) {
if (GetOptions() == (kHorizontalFrame | kSunkenFrame | kDoubleBorder)) {
out <<");" << endl;
} else {
out << "," << GetOptionString() << ");" << endl;
}
} else {
out << "," << GetOptionString() << ",ucolor);" << endl;
}
TGTextLBEntry *b;
TGFrameElement *el;
TGListBox *lb = GetListBox();
TIter next(((TGLBContainer *)lb->GetContainer())->GetList());
while ((el = (TGFrameElement *) next())) {
b = (TGTextLBEntry *) el->fFrame;
out << " " << GetName() << "->AddEntry(";
b->SavePrimitive(out, option);
out << ");" << endl;
}
out << " " << GetName() << "->Resize(" << GetWidth() << ","
<< GetHeight() << ");" << endl;
out << " " << GetName() << "->Select(" << GetSelected() << ");" << endl;
}
TGLineStyleComboBox::TGLineStyleComboBox(const TGWindow *p, Int_t id,
UInt_t options, Pixel_t back)
: TGComboBox(p, id, options, back)
{
SetTopEntry(new TGLineLBEntry(this, 0),
new TGLayoutHints(kLHintsLeft | kLHintsExpandY | kLHintsExpandX));
fSelEntry->ChangeOptions(fSelEntry->GetOptions() | kOwnBackground);
for (Int_t i = 1; i <= 10; i++)
AddEntry(new TGLineLBEntry(GetListBox()->GetContainer(), i,
TString::Format("%d",i), 0, i),
new TGLayoutHints(kLHintsTop | kLHintsExpandX));
Select(1, kFALSE);
SetWindowName();
}
void TGLineStyleComboBox::SavePrimitive(ostream &out, Option_t * )
{
out << endl << " // line style combo box" << endl;
out << " TGLineStyleComboBox *";
out << GetName() << " = new TGLineStyleComboBox(" << fParent->GetName()
<< "," << fWidgetId << ");" << endl;
out << " " << GetName() << "->Resize(" << GetWidth() << ","
<< GetHeight() << ");" << endl;
out << " " << GetName() << "->Select(" << GetSelected() << ");" << endl;
}
TGLineWidthComboBox::TGLineWidthComboBox(const TGWindow *p, Int_t id,
UInt_t options, Pixel_t back, Bool_t none)
: TGComboBox(p, id, options, back)
{
SetTopEntry(new TGLineLBEntry(this,0),
new TGLayoutHints(kLHintsLeft | kLHintsExpandY | kLHintsExpandX));
fSelEntry->ChangeOptions(fSelEntry->GetOptions() | kOwnBackground);
if (none) {
AddEntry(new TGLineLBEntry(GetListBox()->GetContainer(), 0, "None", 0, 0),
new TGLayoutHints(kLHintsTop | kLHintsExpandX));
}
for (Int_t i = 1; i < 16; i++)
AddEntry(new TGLineLBEntry(GetListBox()->GetContainer(), i,
TString::Format("%d",i), i, 0),
new TGLayoutHints(kLHintsTop | kLHintsExpandX));
Select(1, kFALSE);
SetWindowName();
}
void TGLineWidthComboBox::SavePrimitive(ostream &out, Option_t * )
{
out << endl << " // line width combo box" << endl;
out << " TGLineWidthComboBox *";
out << GetName() << " = new TGLineWidthComboBox(" << fParent->GetName()
<< "," << fWidgetId << ");" << endl;
out << " " << GetName() << "->Resize(" << GetWidth() << ","
<< GetHeight() << ");" << endl;
out << " " << GetName() << "->Select(" << GetSelected() << ");" << endl;
}
static const char *gFonts[][2] = {
{ "", "" },
{ "-*-times-medium-i-*-*-12-*-*-*-*-*-*-*", "1. times italic" },
{ "-*-times-bold-r-*-*-12-*-*-*-*-*-*-*", "2. times bold" },
{ "-*-times-bold-i-*-*-12-*-*-*-*-*-*-*", "3. times bold italic" },
{ "-*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", "4. helvetica" },
{ "-*-helvetica-medium-o-*-*-12-*-*-*-*-*-*-*", "5. helvetica italic" },
{ "-*-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*", "6. helvetica bold" },
{ "-*-helvetica-bold-o-*-*-12-*-*-*-*-*-*-*", "7. helvetica bold italic" },
{ "-*-courier-medium-r-*-*-12-*-*-*-*-*-*-*", "8. courier" },
{ "-*-courier-medium-o-*-*-12-*-*-*-*-*-*-*", "9. courier italic" },
{ "-*-courier-bold-r-*-*-12-*-*-*-*-*-*-*", "10. courier bold" },
{ "-*-courier-bold-o-*-*-12-*-*-*-*-*-*-*", "11. courier bold italic" },
{ "-*-symbol-medium-r-*-*-12-*-*-*-*-*-*-*", "12. symbol" },
{ "-*-times-medium-r-*-*-12-*-*-*-*-*-*-*", "13. times" },
{ 0, 0}
};
TGFontTypeComboBox::TGFontTypeComboBox(const TGWindow *p, Int_t id,
UInt_t options, Pixel_t back) :
TGComboBox(p, id, options, back)
{
Int_t noFonts = 0;
for (Int_t i = 1; gFonts[i][0] != 0 && noFonts < kMaxFonts; i++) {
fFonts[noFonts] = gVirtualX->LoadQueryFont(gFonts[i][0]);
if (fFonts[noFonts] == 0)
fFonts[noFonts] = TGTextLBEntry::GetDefaultFontStruct();
GCValues_t gval;
gval.fMask = kGCFont;
gval.fFont = gVirtualX->GetFontHandle(fFonts[noFonts]);
AddEntry(new TGTextLBEntry(GetListBox()->GetContainer(),
new TGString(gFonts[i][1]), i,
fClient->GetGC(&gval, kTRUE)->GetGC(), fFonts[noFonts]),
new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX));
noFonts++;
}
if (noFonts < kMaxFonts - 1)
fFonts[noFonts] = 0;
Select(1, kFALSE);
SetWindowName();
}
TGFontTypeComboBox::~TGFontTypeComboBox()
{
for (int i = 0; i < kMaxFonts && fFonts[i] != 0; i++)
gVirtualX->DeleteFont(fFonts[i]);
}