1 /********************************************************************************
2 * *
3 * C h o i c e B o x *
4 * *
5 *********************************************************************************
6 * Copyright (C) 2004,2020 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as published by *
10 * the Free Software Foundation; either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/> *
20 ********************************************************************************/
21 #include "xincs.h"
22 #include "fxver.h"
23 #include "fxdefs.h"
24 #include "fxmath.h"
25 #include "FXArray.h"
26 #include "FXHash.h"
27 #include "FXMutex.h"
28 #include "FXStream.h"
29 #include "FXString.h"
30 #include "FXSize.h"
31 #include "FXPoint.h"
32 #include "FXRectangle.h"
33 #include "FXObjectList.h"
34 #include "FXStringDictionary.h"
35 #include "FXSettings.h"
36 #include "FXRegistry.h"
37 #include "FXAccelTable.h"
38 #include "FXEvent.h"
39 #include "FXWindow.h"
40 #include "FXApp.h"
41 #include "FXIcon.h"
42 #include "FXSeparator.h"
43 #include "FXLabel.h"
44 #include "FXButton.h"
45 #include "FXHorizontalFrame.h"
46 #include "FXVerticalFrame.h"
47 #include "FXScrollBar.h"
48 #include "FXList.h"
49 #include "FXChoiceBox.h"
50 #include "icons.h"
51
52 /*
53 Notes:
54 - Maybe allow setting initial value which selected.
55 - Maybe have multiple choice capability.
56 - Maybe have list of icons for each list item.
57 */
58
59 // Padding for message box buttons
60 #define HORZ_PAD 30
61 #define VERT_PAD 2
62
63 using namespace FX;
64
65 /*******************************************************************************/
66
67 namespace FX {
68
69 // Map
70 FXDEFMAP(FXChoiceBox) FXChoiceBoxMap[]={
71 FXMAPFUNC(SEL_COMMAND,FXChoiceBox::ID_CANCEL,FXChoiceBox::onCmdCancel),
72 FXMAPFUNC(SEL_COMMAND,FXChoiceBox::ID_ACCEPT,FXChoiceBox::onCmdClicked),
73 FXMAPFUNC(SEL_DOUBLECLICKED,FXChoiceBox::ID_CLICKED,FXChoiceBox::onCmdClicked),
74 };
75
76
77
78 // Object implementation
FXIMPLEMENT(FXChoiceBox,FXDialogBox,FXChoiceBoxMap,ARRAYNUMBER (FXChoiceBoxMap))79 FXIMPLEMENT(FXChoiceBox,FXDialogBox,FXChoiceBoxMap,ARRAYNUMBER(FXChoiceBoxMap))
80
81
82 // Construct choice box with given caption, icon, message text, and with choices from array of strings
83 FXChoiceBox::FXChoiceBox(FXWindow* own,const FXString& caption,const FXString& text,FXIcon* icn,const FXchar** choices,FXuint opts,FXint x,FXint y,FXint w,FXint h):FXDialogBox(own,caption,opts|DECOR_TITLE|DECOR_BORDER,x,y,w,h,10,10,10,10, 10,10){
84 FXint n;
85 initialize(text,icn);
86 n=list->fillItems(choices);
87 list->setNumVisible(FXMIN(n,5));
88 }
89
90
91 // Construct choice box with given caption, icon, message text, and with choices from newline separated strings
FXChoiceBox(FXWindow * own,const FXString & caption,const FXString & text,FXIcon * icn,const FXString & choices,FXuint opts,FXint x,FXint y,FXint w,FXint h)92 FXChoiceBox::FXChoiceBox(FXWindow* own,const FXString& caption,const FXString& text,FXIcon* icn,const FXString& choices,FXuint opts,FXint x,FXint y,FXint w,FXint h):FXDialogBox(own,caption,opts|DECOR_TITLE|DECOR_BORDER,x,y,w,h,10,10,10,10, 10,10){
93 FXint n;
94 initialize(text,icn);
95 n=list->fillItems(choices);
96 list->setNumVisible(FXMIN(n,5));
97 }
98
99
100 // Construct free floating choice box with given caption, icon, message text, and with choices from array of strings
FXChoiceBox(FXApp * a,const FXString & caption,const FXString & text,FXIcon * icn,const FXchar ** choices,FXuint opts,FXint x,FXint y,FXint w,FXint h)101 FXChoiceBox::FXChoiceBox(FXApp* a,const FXString& caption,const FXString& text,FXIcon* icn,const FXchar** choices,FXuint opts,FXint x,FXint y,FXint w,FXint h):FXDialogBox(a,caption,opts|DECOR_TITLE|DECOR_BORDER,x,y,w,h,10,10,10,10, 10,10){
102 FXint n;
103 initialize(text,icn);
104 n=list->fillItems(choices);
105 list->setNumVisible(FXMIN(n,5));
106 }
107
108
109 // Construct free floating choice box with given caption, icon, message text, and with choices from newline separated strings
FXChoiceBox(FXApp * a,const FXString & caption,const FXString & text,FXIcon * icn,const FXString & choices,FXuint opts,FXint x,FXint y,FXint w,FXint h)110 FXChoiceBox::FXChoiceBox(FXApp* a,const FXString& caption,const FXString& text,FXIcon* icn,const FXString& choices,FXuint opts,FXint x,FXint y,FXint w,FXint h):FXDialogBox(a,caption,opts|DECOR_TITLE|DECOR_BORDER,x,y,w,h,10,10,10,10, 10,10){
111 FXint n;
112 initialize(text,icn);
113 n=list->fillItems(choices);
114 list->setNumVisible(FXMIN(n,5));
115 }
116
117
118 // Build contents
initialize(const FXString & text,FXIcon * icn)119 void FXChoiceBox::initialize(const FXString& text,FXIcon* icn){
120 FXHorizontalFrame* buttons=new FXHorizontalFrame(this,LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X|PACK_UNIFORM_WIDTH,0,0,0,0,0,0,0,0);
121 new FXButton(buttons,tr("&OK"),NULL,this,ID_ACCEPT,BUTTON_INITIAL|BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_RIGHT,0,0,0,0,HORZ_PAD,HORZ_PAD,VERT_PAD,VERT_PAD);
122 new FXButton(buttons,tr("&Cancel"),NULL,this,ID_CANCEL,BUTTON_DEFAULT|FRAME_RAISED|FRAME_THICK|LAYOUT_CENTER_Y|LAYOUT_RIGHT,0,0,0,0,HORZ_PAD,HORZ_PAD,VERT_PAD,VERT_PAD);
123 new FXHorizontalSeparator(this,SEPARATOR_GROOVE|LAYOUT_SIDE_BOTTOM|LAYOUT_FILL_X);
124 FXHorizontalFrame* toppart=new FXHorizontalFrame(this,LAYOUT_SIDE_TOP|LAYOUT_FILL_X,0,0,0,0, 0,0,0,0, 10,10);
125 new FXLabel(toppart,FXString::null,icn,ICON_BEFORE_TEXT|JUSTIFY_CENTER_X|JUSTIFY_CENTER_Y|LAYOUT_FILL_Y|LAYOUT_FILL_X);
126 new FXLabel(toppart,text,NULL,JUSTIFY_LEFT|ICON_BEFORE_TEXT|LAYOUT_TOP|LAYOUT_LEFT|LAYOUT_FILL_X);
127 FXHorizontalFrame* midpart=new FXHorizontalFrame(this,FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 0,0,0,0, 10,10);
128 list=new FXList(midpart,this,ID_CLICKED,LIST_BROWSESELECT|LAYOUT_FILL_Y|LAYOUT_FILL_X|HSCROLLING_OFF);
129 }
130
131
132 // Close dialog when double-clicked in list or hit accept
onCmdClicked(FXObject *,FXSelector,void *)133 long FXChoiceBox::onCmdClicked(FXObject*,FXSelector,void*){
134 getApp()->stopModal(this,list->getCurrentItem());
135 hide();
136 return 1;
137 }
138
139
140 // Close dialog with a cancel
onCmdCancel(FXObject *,FXSelector,void *)141 long FXChoiceBox::onCmdCancel(FXObject*,FXSelector,void*){
142 getApp()->stopModal(this,-1);
143 hide();
144 return 1;
145 }
146
147
148 // We have to do this so as to force the initial text to be seleced
execute(FXuint placement)149 FXuint FXChoiceBox::execute(FXuint placement){
150 create();
151 list->setFocus();
152 show(placement);
153 return getApp()->runModalFor(this);
154 }
155
156
157 // Save object to stream
save(FXStream & store) const158 void FXChoiceBox::save(FXStream& store) const {
159 FXDialogBox::save(store);
160 store << list;
161 }
162
163
164 // Load object from stream
load(FXStream & store)165 void FXChoiceBox::load(FXStream& store){
166 FXDialogBox::load(store);
167 store >> list;
168 }
169
170
171 // Destroy choice box
~FXChoiceBox()172 FXChoiceBox::~FXChoiceBox(){
173 list=(FXList*)-1L;
174 }
175
176
177 /*******************************************************************************/
178
179
180 // Show a modal choice dialog
ask(FXWindow * owner,FXuint opts,const FXString & caption,const FXString & text,FXIcon * icon,const FXchar ** choices)181 FXint FXChoiceBox::ask(FXWindow* owner,FXuint opts,const FXString& caption,const FXString& text,FXIcon* icon,const FXchar** choices){
182 FXChoiceBox box(owner,caption,text,icon,choices,opts);
183 return box.execute(PLACEMENT_OWNER);
184 }
185
186
187 // Show a modal choice dialog
ask(FXWindow * owner,FXuint opts,const FXString & caption,const FXString & text,FXIcon * icon,const FXString & choices)188 FXint FXChoiceBox::ask(FXWindow* owner,FXuint opts,const FXString& caption,const FXString& text,FXIcon* icon,const FXString& choices){
189 FXChoiceBox box(owner,caption,text,icon,choices,opts);
190 return box.execute(PLACEMENT_OWNER);
191 }
192
193
194 // Show a modal choice dialog, in free floating window
ask(FXApp * app,FXuint opts,const FXString & caption,const FXString & text,FXIcon * icon,const FXchar ** choices)195 FXint FXChoiceBox::ask(FXApp* app,FXuint opts,const FXString& caption,const FXString& text,FXIcon* icon,const FXchar** choices){
196 FXChoiceBox box(app,caption,text,icon,choices,opts);
197 return box.execute(PLACEMENT_SCREEN);
198 }
199
200
201 // Show a modal choice dialog, in free floating window
ask(FXApp * app,FXuint opts,const FXString & caption,const FXString & text,FXIcon * icon,const FXString & choices)202 FXint FXChoiceBox::ask(FXApp* app,FXuint opts,const FXString& caption,const FXString& text,FXIcon* icon,const FXString& choices){
203 FXChoiceBox box(app,caption,text,icon,choices,opts);
204 return box.execute(PLACEMENT_SCREEN);
205 }
206
207 }
208
209