1 /***************************************************************************
2 gdlwidget.cpp - GDL widget system implementation
3 -------------------
4 begin : Fri May 7 2004
5 copyright : (C) 2004 by Marc Schellens
6 email : m_schellens@users.sourceforge.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "includefirst.hpp"
19
20 #ifdef HAVE_LIBWXWIDGETS
21
22 #include <memory>
23
24 #include <wx/grid.h>
25 #include <wx/gbsizer.h>
26 #include <wx/wrapsizer.h>
27 #include <wx/textctrl.h>
28 #include <wx/menuitem.h>
29
30 #include "basegdl.hpp"
31 #include "dstructgdl.hpp"
32
33 #include "dinterpreter.hpp"
34
35
36 #include "gdlwxstream.hpp"
37
38 #include "gdlwidget.hpp"
39
40 #include "widget.hpp"
41 #include "graphicsdevice.hpp"
42
43 //must arrive after "gdlwidget.hpp"
44 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
45 #include <random>
46 #include <chrono>
47 #endif
48
49 //abbrevs to avoid sending size events when changing sizes
50 #define START_CHANGESIZE_NOEVENT \
51 WidgetIDT id;\
52 gdlwxFrame* local_topFrame;\
53 bool reconnect=this->DisableSizeEvents(local_topFrame,id);
54
55 #define END_CHANGESIZE_NOEVENT if (reconnect) EnableSizeEvents(local_topFrame,id);
56
57 #define START_ADD_EVENTUAL_FRAME \
58 wxScrolled<wxPanel>* saveWidgetPanel = widgetPanel;\
59 wxSizer* frameSizer;\
60 if (frameWidth > 0) {\
61 framePanel = new wxPanel(widgetPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, gdlBORDER_EXT);\
62 frameSizer = new wxBoxSizer(wxVERTICAL);\
63 framePanel->SetSizer(frameSizer);\
64 widgetPanel = static_cast<wxScrolled<wxPanel>*>(framePanel);\
65 }
66
67 #define END_ADD_EVENTUAL_FRAME \
68 if (frameWidth > 0) {\
69 theWxContainer = widgetPanel;\
70 frameSizer->Add(static_cast<wxWindow*> (theWxWidget), ALLOWSTRETCH, wxALL|wxEXPAND , frameWidth);\
71 frameSizer->Fit(static_cast<wxWindow*> (theWxWidget));\
72 framePanel->Fit();\
73 widgetPanel = saveWidgetPanel;\
74 }
75
76 #define TIDY_WIDGET(xxx) \
77 this->setFont();\
78 if (widgetSizer) {\
79 /*if we create a widget after the topwidget has been realized, insure the insertion is IDL-compliant for multicolumns, using the following; */\
80 /* 1) recompute the base siser taking into account the additional widget to be inserted */\
81 /* 2) recreate the adequate sizer */\
82 /* 3) re-add all child windows (including this one) */\
83 if (this->IsRealized()) {\
84 GDLWidgetBase* b = static_cast<GDLWidgetBase*> (gdlParent);\
85 b->ReorderForANewWidget(static_cast<wxWindow*> (theWxContainer), DONOTALLOWSTRETCH, widgetStyle | wxALL, b->getSpace());\
86 } else widgetSizer->Add(static_cast<wxWindow*> (theWxContainer), DONOTALLOWSTRETCH, widgetStyle | wxALL, xxx);\
87 } else {\
88 static_cast<wxWindow*> (theWxContainer)->SetPosition(wOffset);\
89 }\
90 widgetPanel->FitInside();
91
92 #define UPDATE_WINDOW { if (this->IsRealized()) UpdateGui(); }
93 #define REALIZE_IF_NEEDED { if (this->IsRealized()) {this->OnRealize(); UpdateGui();} }
94
95 //a few useful defaut pixmaps:
96 static const char * pixmap_unchecked[] = {
97 "13 13 14 1",
98 " c None",
99 ". c #CCCED3",
100 "+ c #838793",
101 "@ c #C4C7CF",
102 "# c #F5F5F5",
103 "$ c #F6F6F6",
104 "% c #F7F7F7",
105 "& c #F9F9F9",
106 "* c #FAFAFA",
107 "= c #FBFBFB",
108 "- c #FCFCFC",
109 "; c #FDFDFD",
110 "> c #FEFEFE",
111 ", c #FFFFFF",
112 ".+++++++++++.",
113 "+@@@@@@@@@@@+",
114 "+@##########+",
115 "+@$$$$$$$$$$+",
116 "+@%%%%%%%%%%+",
117 "+@&&&&&&&&&&+",
118 "+@**********+",
119 "+@==========+",
120 "+@----------+",
121 "+@;;;;;;;;;;+",
122 "+@>>>>>>>>>>+",
123 "+@,,,,,,,,,,+",
124 ".+++++++++++."};
125
126 static const char * pixmap_checked[] = {
127 "13 13 38 1",
128 " c None",
129 ". c #CCCED3",
130 "+ c #838793",
131 "@ c #C4C7CF",
132 "# c #F5F5F5",
133 "$ c #BBBBBB",
134 "% c #131313",
135 "& c #0C0C0C",
136 "* c #F6F6F6",
137 "= c #BEBEBE",
138 "- c #030303",
139 "; c #060606",
140 "> c #B4B4B4",
141 ", c #F7F7F7",
142 "' c #C6C6C6",
143 ") c #080808",
144 "! c #000000",
145 "~ c #C0C0C0",
146 "{ c #020202",
147 "] c #363636",
148 "^ c #F9F9F9",
149 "/ c #505050",
150 "( c #2C2C2C",
151 "_ c #545454",
152 ": c #606060",
153 "< c #010101",
154 "[ c #FAFAFA",
155 "} c #FBFBFB",
156 "| c #333333",
157 "1 c #1D1D1D",
158 "2 c #FCFCFC",
159 "3 c #C4C4C4",
160 "4 c #FDFDFD",
161 "5 c #B9B9B9",
162 "6 c #FEFEFE",
163 "7 c #5E5E5E",
164 "8 c #777777",
165 "9 c #FFFFFF",
166 ".+++++++++++.",
167 "+@@@@@@@@@@@+",
168 "+@######$%&#+",
169 "+@*****=-;**+",
170 "+@$>,,')!~,,+",
171 "+@{!]^/!(^^^+",
172 "+@_!!:<![[[[+",
173 "+@}|!!!1}}}}+",
174 "+@22)!!32222+",
175 "+@445!)44444+",
176 "+@6667866666+",
177 "+@9999999999+",
178 ".+++++++++++."};
179
180
181 const WidgetIDT GDLWidget::NullID = 0;
182
183 // instantiation
184 WidgetListT GDLWidget::widgetList;
185 wxImageList *gdlDefaultTreeStateImages;
186 wxImageList *gdlDefaultTreeImages;
187
188 GDLEventQueue GDLWidget::eventQueue; // the event queue
189 GDLEventQueue GDLWidget::readlineEventQueue; // for process at command line level
190 bool GDLWidget::wxIsOn=false;
191 bool GDLWidget::handlersOk=false;
192 wxFont GDLWidget::defaultFont=wxNullFont; //the font defined by widget_control,default_font.
193 wxFont GDLWidget::systemFont=wxNullFont; //the initial system font. This to behave as IDL
194
195
Purge()196 void GDLEventQueue::Purge()
197 {
198 for ( SizeT i = 0; i < dq.size( ); ++i )
199 delete dq[i];
200 dq.clear( );
201 // isEmpty = true;
202 }
203
204 // removes all events for hierarchy staring at 'parentID' and below
Purge(WidgetIDT parentID)205 void GDLEventQueue::Purge( WidgetIDT parentID) {
206 //establish a list of children:
207 GDLWidget* w = GDLWidget::GetWidget(parentID);
208 DLongGDL* list = w->GetAllHeirs();
209 for (long i = dq.size() - 1; i >= 0; --i) {
210 DStructGDL* ev = dq[i];
211 static int idIx = 0; // ev->Desc( )->TagIndex( "ID" ); //always 0
212 DLong id = (*static_cast<DLongGDL*> (ev->GetTag(idIx, 0)))[0];
213 //all events pertaining to any heirs of 'parentID' including 'parentID' are removed:
214 for (DLong testid = 0; testid < list->N_Elements(); ++testid) {
215 if (id == (*list)[testid]) {
216 // std::cerr<<"event "<<id<<" purged."<<std::endl;
217 delete ev;
218 dq.erase(dq.begin() + i);
219 }
220 }
221 }
222 GDLDelete(list);
223 // isEmpty = true;
224 }
225 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
RandomWxColour()226 inline wxColour RandomWxColour() {
227 unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
228 std::default_random_engine generator (seed);
229
230 std::uniform_int_distribution<int> distribution(0,255);
231 int r = distribution(generator);
232 int g = distribution(generator);
233 int b = distribution(generator);
234 return wxColour(r,g,b);
235 }
236 #endif
237
238 //this seem to respect the order of preference if variuos align_xxx are passed to the widget.
labelTextAlignment()239 inline int GDLWidget::labelTextAlignment()
240 {//this concerns only how the thext is written in the label.
241 // Top and bottom are not allowed in IDL.
242 if ( alignment & gdlwALIGN_RIGHT ) return (wxALIGN_RIGHT|wxST_NO_AUTORESIZE);
243 if ( alignment & gdlwALIGN_CENTER ) return (wxALIGN_CENTRE_HORIZONTAL|wxST_NO_AUTORESIZE);
244 if ( alignment & gdlwALIGN_LEFT ) return (wxALIGN_LEFT|wxST_NO_AUTORESIZE);
245 return wxALIGN_CENTRE_HORIZONTAL|wxST_NO_AUTORESIZE;
246 }
247
buttonTextAlignment()248 inline int GDLWidget::buttonTextAlignment()
249 { //this concerns only how the thext is written in the button. Apparently wxBU_RIGHT does not work, and center is absent.
250 // Top and bottom are not allowed in IDL.
251 if ( alignment & gdlwALIGN_RIGHT ) return wxBU_EXACTFIT|wxBU_RIGHT; //right does not work.
252 if ( alignment & gdlwALIGN_CENTER ) return wxBU_EXACTFIT; //center does not exist
253 if ( alignment & gdlwALIGN_LEFT ) return wxBU_EXACTFIT|wxBU_LEFT; //default, works
254 return wxBU_EXACTFIT;
255 }
256
widgetAlignment()257 inline int GDLWidgetLabel::widgetAlignment()
258 {
259 long myAlign = alignment;
260 if (myAlign == gdlwALIGN_NOT) {
261 myAlign = this->GetMyParentBaseWidget()->getChildrenAlignment();
262 }
263 //wxALIGN_LEFT and TOP is in fact wxALIGN_NOT as this is the default alignment
264 if (myAlign == gdlwALIGN_NOT) return wxALIGN_CENTER;
265 //left is top by default and right is bottom. So define left as top and remove top if bottom, etc.
266 //ignore sets that do not concern the current layout (vetrtical or horizontal)
267 if (this->GetMyParentBaseWidget()->IsVertical()) { //col=1 left, center, right
268 if (myAlign & gdlwALIGN_CENTER) return wxALIGN_CENTER_HORIZONTAL;
269 if (myAlign & gdlwALIGN_LEFT) return wxALIGN_LEFT;
270 if (myAlign & gdlwALIGN_RIGHT) return wxALIGN_RIGHT;
271 if (myAlign & gdlwALIGN_TOP) return wxALIGN_LEFT;
272 if (myAlign & gdlwALIGN_BOTTOM) return wxALIGN_RIGHT;
273 } else if (this->GetMyParentBaseWidget()->IsHorizontal()) { //row=1
274 if (myAlign & gdlwALIGN_CENTER) return wxALIGN_CENTER_VERTICAL;
275 if (myAlign & gdlwALIGN_TOP) return wxALIGN_TOP;
276 if (myAlign & gdlwALIGN_BOTTOM) return wxALIGN_BOTTOM;
277 if (myAlign & gdlwALIGN_LEFT) return wxALIGN_TOP;
278 if (myAlign & gdlwALIGN_RIGHT) return wxALIGN_BOTTOM;
279 } else {
280 if (myAlign & gdlwALIGN_CENTER) return wxALIGN_CENTER_HORIZONTAL;
281 if (myAlign & gdlwALIGN_LEFT) return wxALIGN_LEFT;
282 if (myAlign & gdlwALIGN_RIGHT) return wxALIGN_RIGHT;
283 if (myAlign & gdlwALIGN_TOP) return wxALIGN_LEFT;
284 if (myAlign & gdlwALIGN_BOTTOM) return wxALIGN_RIGHT;
285 }
286 return 0;
287 }
288
widgetAlignment()289 inline int GDLWidget::widgetAlignment()
290 {
291 long myAlign = alignment;
292 if (myAlign == gdlwALIGN_NOT) {
293 myAlign = this->GetMyParentBaseWidget()->getChildrenAlignment();
294 }
295 //wxALIGN_LEFT and TOP is in fact wxALIGN_NOT as this is the default alignment
296 long expand=wxEXPAND;
297 if (this->IsLabel()) expand=0; //labels are not expanded
298 if (this->IsDraw()) expand=0; //draw are not expanded
299 if (myAlign == gdlwALIGN_NOT) return expand|wxALIGN_LEFT|wxALIGN_TOP;
300 //left is top by default and right is bottom. So define left as top and remove top if bottom, etc.
301 //ignore sets that do not concern the current layout (vetrtical or horizontal)
302 if (this->GetMyParentBaseWidget()->IsVertical()) { //col=1 left, center, right
303 if (myAlign & gdlwALIGN_CENTER) return wxALIGN_CENTER_HORIZONTAL;
304 if (myAlign & gdlwALIGN_LEFT) return wxALIGN_LEFT;
305 if (myAlign & gdlwALIGN_RIGHT) return wxALIGN_RIGHT;
306 if (myAlign & gdlwALIGN_TOP) return wxALIGN_LEFT;
307 if (myAlign & gdlwALIGN_BOTTOM) return wxALIGN_RIGHT;
308 } else if (this->GetMyParentBaseWidget()->IsHorizontal()) { //row=1
309 if (myAlign & gdlwALIGN_CENTER) return wxALIGN_CENTER_VERTICAL;
310 if (myAlign & gdlwALIGN_TOP) return wxALIGN_TOP;
311 if (myAlign & gdlwALIGN_BOTTOM) return wxALIGN_BOTTOM;
312 if (myAlign & gdlwALIGN_LEFT) return wxALIGN_TOP;
313 if (myAlign & gdlwALIGN_RIGHT) return wxALIGN_BOTTOM;
314 }
315 return 0;
316 }
317
setFont()318 void GDLWidget::setFont() {
319 wxWindow* w = dynamic_cast<wxWindow*> (this->GetWxWidget());
320 if (w != NULL) w->SetFont(font); //may be menu: this is ok
321 }
setFont(wxObject * o)322 void GDLWidget::setFont(wxObject* o) {
323 wxWindow* w = dynamic_cast<wxWindow*> (o);
324 if (w != NULL) w->SetFont(font);
325 }
326
AddABaseSizer(DLong col,DLong row,bool grid,long space)327 inline wxSizer* AddABaseSizer(DLong col, DLong row, bool grid, long space)
328 {
329 if (row <= 0 && col <= 0) return NULL;
330 //This to mimic the disposal of children in IDL's Bases, where the 'packing' is more clever
331 //than in wxWidgets, we will ALWAYS use a ROW gridding, where the number of rows is
332 //deduced from the number of cols and of children when this number is known...
333 //..which is not the case for us until the wigdet is realized, and ReorderWidgets() is called.
334 //So the col >1 case below is a bit irrelevant as it will be recomputed.
335 //In this case (col >1) we do not create a base Sizer, it will be created in ReorderWidgets().
336 //We also need to use a BoxSizer for col==1 or row==1 as only BoxSizer is able to strectch correctly.
337 if (row==1 && space < 1) {
338 wxBoxSizer* s=new wxBoxSizer(wxHORIZONTAL);
339 return s;
340 }
341 if (col==1 && space < 1) {
342 wxBoxSizer* s=new wxBoxSizer(wxVERTICAL);
343 return s;
344 }
345 // grid behaviour of Motif (IDL) is not as perfect as wxWidget's. We cannot use wxGridSizer here,
346 // the trick is to set only the non-flexible grow mode
347
348 if (row>0) {
349 wxFlexGridSizer* s=new wxFlexGridSizer(row,0,space,space);
350 if (grid) {
351 s->SetFlexibleDirection(wxVERTICAL);
352 s->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL);
353 }
354 return s;
355 }
356 // if (col>0) { //will be treated only at realize time, since default order is not good.
357 // return NULL;
358 // }
359 if (col>0) {
360 wxFlexGridSizer* s=new wxFlexGridSizer(0,col,space,space);
361 if (grid) {
362 s->SetFlexibleDirection(wxHORIZONTAL);
363 s->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL);
364 }
365 return s;
366 }
367 return NULL;
368 }
369
370 //returns the current (widget or default) fontSize, taking care a typical width is returned instead of 0 as it is the case for variable pitch fonts, at least under windows
getFontSize()371 inline wxSize GDLWidget::getFontSize() {
372 wxSize fontSize = defaultFont.GetPixelSize();
373 if (!font.IsSameAs(wxNullFont)) fontSize = font.GetPixelSize();
374 // under Windows, as of today: problem getting sizes
375 if (fontSize.x < 1 || fontSize.y < 1 ) { //do it ourselves
376 wxScreenDC dc;
377 dc.SetFont(font);
378 fontSize=dc.GetTextExtent(wxString('M'));
379 }
380 return fontSize;
381 }
382
383 // return the size of text (pixels) as it will take if displayed with current or given font
calculateTextScreenSize(std::string & s,wxFont testFont)384 wxSize GDLWidget::calculateTextScreenSize(std::string &s, wxFont testFont) {
385 wxFont f=font; //current font
386 if (testFont!=wxNullFont) f = testFont;
387 wxScreenDC dc;
388 dc.SetFont(f);
389 return dc.GetTextExtent(wxString(s.c_str( ), wxConvUTF8));
390 }
391
computeWidgetSize()392 inline wxSize GDLWidgetText::computeWidgetSize()
393 {
394 wxWindow* me = dynamic_cast<wxWindow*> (this->GetWxWidget());
395 //widget text size is in LINES in Y and CHARACTERS in X. But overridden by scr_xsize et if present
396 wxRealPoint widgetSize = wxRealPoint(-1,-1);
397 // wxSize fontSize = getFontSize();
398 static std::string testExtent("M");
399 wxSize fontSize=calculateTextScreenSize(testExtent); //use text extent of an EM for realistic fontSize.
400 int lineHeight=fontSize.y;
401 if (textSize.x > 0) {
402 widgetSize.x = (textSize.x) * fontSize.x;
403 } else {
404 widgetSize.x = maxlinelength*fontSize.x;//add 2 char wide for border.
405 textSize.x=maxlinelength;
406 if (textSize.x < 20) {
407 textSize.x=20;
408 widgetSize.x = (textSize.x) * fontSize.x;
409 }
410 }
411
412 if (textSize.y > 1) {
413 widgetSize.y = textSize.y * lineHeight;
414 } else {
415 widgetSize.y = lineHeight;
416 textSize.y = 1;
417 }
418 if (textSize.y ==1) widgetSize.y+=2*gdlTEXT_SPACE; //for margin
419 if (scrolled && textSize.y >1) widgetSize.x+=gdlSCROLL_WIDTH_Y;
420
421 //if multiline and no hscroll, a x-axis scrollbar will be adde by wxWidgets if longestLineSize cannot be shown, and we cannot do anything about it.
422 if (!scrolled) {if (textSize.y > 1 && (textSize.x < maxlinelength) ) widgetSize.y += gdlSCROLL_HEIGHT_X; }
423 else if (textSize.y > 1 && widgetSize.x < (maxlinelength*fontSize.x+gdlSCROLL_WIDTH_Y) ) {
424 widgetSize.y += gdlSCROLL_HEIGHT_X;
425 }
426 widgetSize.x+=2*gdlTEXT_SPACE; //for margin
427
428 //but..
429 if (wScreenSize.x > 0) widgetSize.x = wScreenSize.x;
430 if (wScreenSize.y > 0) widgetSize.y = wScreenSize.y;
431
432 int x = ceil(widgetSize.x);
433 int y = ceil(widgetSize.y);
434 //memorize the current textSize, in characters.
435 initialSize=textSize;
436 return wxSize(x, y);
437 }
438
computeWidgetSize()439 inline wxSize GDLWidgetList::computeWidgetSize()
440 {
441 //default wxChoice sizing is 2 lines, lines are well-separated. default IDL is only 1 line. Thus we need to fix sizes
442
443 //widget text size is in LINES in Y and CHARACTERS in X. But overridden by scr_xsize et if present
444 wxRealPoint widgetSize = wxRealPoint(-1,-1);
445 wxSize fontSize = getFontSize();
446 //based on experience, actual line height is 1.2 times font y size for fonts > 20 but 1.5 for smaller fonts
447 int lineHeight=(fontSize.y<20)?fontSize.y*1.5:fontSize.y*1.2;
448 if (wSize.x > 0) {
449 widgetSize.x = (wSize.x+1) * fontSize.x;
450 } else {
451 widgetSize.x = ( maxlinelength+1 ) * fontSize.x;
452 }
453
454 if (wSize.y > 0) {
455 widgetSize.y = wSize.y * lineHeight;
456 } else {
457 widgetSize.y = lineHeight;
458 }
459
460 if (wSize.x > 0 && maxlinelength > wSize.x) widgetSize.y += gdlSCROLL_HEIGHT_X;
461 if (nlines > wSize.y) widgetSize.x += gdlSCROLL_WIDTH_Y;
462 widgetSize.y += 10;
463 //but..
464 if (wScreenSize.x > 0 ) widgetSize.x = wScreenSize.x; //we need an integer value
465 if (wScreenSize.y > 0) widgetSize.y = wScreenSize.y;
466
467 int x=ceil(widgetSize.x); int y=ceil(widgetSize.y);
468 return wxSize(x,y);
469 }
470
computeWidgetSize()471 inline wxSize GDLWidgetLabel::computeWidgetSize()
472 {
473 if (wSize.x > 0 || wSize.y > 0 || wScreenSize.x > 0 || wScreenSize.y > 0) dynamicResize=-1;
474 //widget label size is in pixels.
475 wxSize widgetSize = wSize; //start with wanted values.
476 wxSize fontSize = getFontSize();
477 //based on experience, actual line height is 1.2 times font y size for fonts > 20 but 1.5 for smaller fonts
478 int lineHeight = fontSize.y+2*gdlLABEL_SPACE ; //(fontSize.y < 20) ? fontSize.y * 1.2 : fontSize.y * 1.2;
479
480 if (wSize.x < 0) widgetSize.x = calculateTextScreenSize(value).x+2*fontSize.x;//add 2 char wide for border. //fontSize.x*(value.size());
481 if (wSize.y < 0) widgetSize.y = lineHeight;
482
483 if (wScreenSize.x > 0) widgetSize.x = wScreenSize.x;
484 if (wScreenSize.y > 0) widgetSize.y = wScreenSize.y;
485
486 if (sunken) {widgetSize.y+=1; widgetSize.x+=1;}
487
488 return widgetSize;
489 }
490
computeWidgetSize()491 inline wxSize GDLWidgetMenuBarButton::computeWidgetSize()
492 {
493 if (wSize.x > 0 || wSize.y > 0 || wScreenSize.x > 0 || wScreenSize.y > 0) dynamicResize=-1;
494 //widget label size is in pixels.
495 wxSize widgetSize = wSize; //start with wanted values.
496 wxSize fontSize = getFontSize();
497 //based on experience, actual line height is 1.2 times font y size for fonts > 20 but 1.5 for smaller fonts
498 int lineHeight = 2*fontSize.y;
499 std::string s=valueWxString.ToStdString();
500 if (wSize.x < 0) widgetSize.x = calculateTextScreenSize(s).x+2*fontSize.x;//add 2 char wide for border. //fontSize.x*(value.size());
501 if (wSize.y < 0) widgetSize.y = lineHeight;
502
503 if (wScreenSize.x > 0) widgetSize.x = wScreenSize.x;
504 if (wScreenSize.y > 0) widgetSize.y = wScreenSize.y;
505
506 return widgetSize;
507 }
computeWidgetSize()508 inline wxSize GDLWidget::computeWidgetSize()
509 {
510 //here is a good place to make dynamic widgets static, since dynamic_resize is permitted only if size is not given.
511 if (wSize.x > 0 || wSize.y > 0 || wScreenSize.x > 0 || wScreenSize.y > 0) dynamicResize=-1;
512 wxSize widgetSize;
513 if ( wSize.x > 0 ) widgetSize.x = wSize.x*unitConversionFactor.x;
514 else widgetSize.x = wxDefaultSize.x;
515 //but..
516 if (wScreenSize.x > 0) widgetSize.x=wScreenSize.x;
517
518 if ( wSize.y > 0 ) widgetSize.y = wSize.y * unitConversionFactor.y;
519 else widgetSize.y = wxDefaultSize.y;
520 //but..
521 if (wScreenSize.y > 0) widgetSize.y=wScreenSize.y;
522
523 return widgetSize;
524 }
525
UpdateGui()526 void GDLWidget::UpdateGui()
527 {
528 //needed to recompute sizes in case of a change of realized widgets or any size change.
529 START_CHANGESIZE_NOEVENT
530
531 WidgetIDT actID = parentID;
532 while ( actID != GDLWidget::NullID ) {
533 GDLWidget *widget = GetWidget( actID );
534 wxPanel* p=widget->GetPanel();
535 if (p) {
536 wxSizer* s = p->GetSizer();
537 if (s) s->Fit(p);
538 else { //force widget having the panel to adopt correct sizes
539 p->Fit();
540 GDLWidgetContainer* myParentContainer = static_cast<GDLWidgetContainer*> (widget->GetMyParentBaseWidget());
541 if (myParentContainer != NULL) {
542 wxWindow* w = static_cast<wxWindow*> (widget->GetParentPanel());
543 assert(w != NULL);
544 wxSize wSize = w->GetSize();
545 wxSize mySize = p->GetSize();
546 // if w.x or w.y was SET BY USER it is a requested size, that we should not change
547 wxSize desiredSize;
548 if (myParentContainer->xFree()) desiredSize.x = max(mySize.x, wSize.x);
549 else {
550 desiredSize.x = wSize.x;
551 }
552 if (myParentContainer->yFree()) desiredSize.y = max(mySize.y, wSize.y);
553 else {
554 desiredSize.y = wSize.y;
555 }
556 w->SetSize(desiredSize);
557 w->SetMinSize(desiredSize);
558 }
559 }
560 }
561 actID = widget->parentID;
562 }
563 this->GetMyTopLevelFrame()->Fit();
564 END_CHANGESIZE_NOEVENT
565 #ifdef __WXMAC__
566 wxTheApp->Yield();
567 #else
568 wxGetApp().MainLoop(); //central loop for wxEvents!
569 #endif
570 }
571
572 //Alternate version if there were sizing problems with the one above.
573 //void GDLWidget::UpdateGui()
574 //{
575 // START_CHANGESIZE_NOEVENT
576 //
577 // // go back to top parent widget while resizing each BASE containers since there must be some update needed.
578 // WidgetIDT actID = widgetID;
579 // while ( actID != GDLWidget::NullID ) {
580 // GDLWidget *widget = GetWidget( actID ); //Not Necessarily a Base
581 // if (widget->IsBase()) {
582 // wxPanel* p=widget->GetPanel();
583 // wxWindow* thisBaseOuterPanel=dynamic_cast<wxWindow*>(widget->GetWxContainer());
584 // wxWindow* thisBaseInnerPanel=dynamic_cast<wxWindow*>(widget->GetWxWidget());
585 // assert((p==thisBaseOuterPanel)||(p==thisBaseInnerPanel));
586 // GDLWidgetBase* b=static_cast<GDLWidgetBase*>(widget);
587 // if (b->IsScrolled()) thisBaseInnerPanel->FitInside(); else thisBaseInnerPanel->Fit();
588 // while (thisBaseOuterPanel!=thisBaseInnerPanel) {
589 // wxSizer* s=thisBaseInnerPanel->GetContainingSizer();
590 // assert (s); //must exist as there are always sizers between theWxContainer ans theWxWidget
591 // s->FitInside(thisBaseInnerPanel);
592 // thisBaseInnerPanel=thisBaseInnerPanel->GetParent();
593 // }
594 // }
595 // actID = widget->parentID;
596 // }
597 // this->GetMyTopLevelFrame()->Fit();
598 // END_CHANGESIZE_NOEVENT
599 //}
600
601 // widget from ID
GetWidget(WidgetIDT widID)602 GDLWidget* GDLWidget::GetWidget( WidgetIDT widID)
603 {
604 if ( widID == GDLWidget::NullID ) return NULL;
605 WidgetListT::iterator it = widgetList.find( widID );
606 if ( it == widgetList.end( ) ) return NULL;
607 return it->second;
608 }
609
610 // widget parent from ID
GetParent(WidgetIDT widID)611 GDLWidget* GDLWidget::GetParent( WidgetIDT widID)
612 {
613 GDLWidget *widget = GetWidget( widID );
614 if ( widget == NULL )
615 return NULL;
616 WidgetIDT parentID = widget->parentID;
617 GDLWidget *parent = GetWidget( parentID );
618 return parent;
619 }
620 // widget parent
GetMyParent()621 GDLWidget* GDLWidget::GetMyParent( ){return GetWidget( parentID ); }
622
EnableWidgetUpdate(bool update)623 void GDLWidget::EnableWidgetUpdate(bool update){
624 wxWindow * me = dynamic_cast<wxWindow*>(theWxWidget);
625 if (me) {if (update) {if ( me->IsFrozen()) me->Thaw(); else me->Refresh(); } else me->Freeze();} else cerr<<"freezing unknown widget\n";
626 }
627
GetMyBaseWidget()628 GDLWidgetBase* GDLWidget::GetMyBaseWidget()
629 {
630 WidgetIDT actID = widgetID;
631 while ( 1 ) {
632 GDLWidget* widget = GetWidget( actID );
633 if ( widget == NULL )
634 return NULL;
635 if ( widget->IsBase( ) )
636 return static_cast<GDLWidgetBase*> (widget);
637 assert( widget->parentID != GDLWidget::NullID );
638 actID = widget->parentID;
639 }
640 }
641
642 // this widget's first parent base widget
GetMyParentBaseWidget()643 GDLWidgetBase* GDLWidget::GetMyParentBaseWidget( )
644 {
645 WidgetIDT actID = parentID;
646 while ( 1 ) {
647 GDLWidget* widget = GetWidget( actID );
648 if ( widget == NULL )
649 return NULL;
650 if ( widget->IsBase( ) )
651 return static_cast<GDLWidgetBase*> (widget);
652 assert( widget->parentID != GDLWidget::NullID );
653 actID = widget->parentID;
654 }
655 }
656
GetBaseId(WidgetIDT widID)657 WidgetIDT GDLWidget::GetBaseId( WidgetIDT widID)
658 {
659 GDLWidget *widget;
660 WidgetIDT actID = widID;
661 while ( 1 ) {
662 GDLWidget* widget = GetWidget( actID );
663 if ( widget == NULL )
664 return GDLWidget::NullID;
665 if ( widget->IsBase( ) )
666 return actID;
667 assert( widget->parentID != GDLWidget::NullID );
668 actID = widget->parentID;
669 }
670 }
671
GetTopLevelBaseWidget(WidgetIDT widID)672 GDLWidgetTopBase* GDLWidget::GetTopLevelBaseWidget( WidgetIDT widID)
673 {
674 WidgetIDT actID = widID;
675 while ( 1 ) {
676 GDLWidget *widget = GetWidget( actID );
677 if ( widget == NULL )
678 return (GDLWidgetTopBase*)GDLWidget::NullID;
679 if ( widget->parentID == GDLWidget::NullID )
680 return static_cast<GDLWidgetTopBase*> (widget);
681 else
682 actID = widget->parentID;
683 }
684 }
685
GetMyTopLevelBaseWidget()686 GDLWidgetTopBase* GDLWidget::GetMyTopLevelBaseWidget()
687 {
688 WidgetIDT actID = this->GetWidgetID();
689 while ( 1 ) {
690 GDLWidget *widget = GetWidget( actID );
691 if ( widget == NULL )
692 return (GDLWidgetTopBase*)GDLWidget::NullID;
693 if ( widget->parentID == GDLWidget::NullID )
694 return static_cast<GDLWidgetTopBase*> (widget);
695 else
696 actID = widget->parentID;
697 }
698 }
699
GetMyTopLevelFrame()700 gdlwxFrame* GDLWidget::GetMyTopLevelFrame()
701 {
702 WidgetIDT actID = this->GetWidgetID();
703 while ( 1 ) {
704 GDLWidget *widget = GetWidget( actID );
705 if ( widget == NULL )
706 return (gdlwxFrame*) NULL;
707 if ( widget->parentID == GDLWidget::NullID )
708 return static_cast<GDLWidgetTopBase*>(widget)->GetTopFrame();
709 else
710 actID = widget->parentID;
711 }
712 }
GetIdOfTopLevelBase(WidgetIDT widID)713 WidgetIDT GDLWidget::GetIdOfTopLevelBase( WidgetIDT widID)
714 {
715 WidgetIDT actID = widID;
716 while ( 1 ) {
717 GDLWidget *widget = GetWidget( actID );
718 if ( widget == NULL )
719 return GDLWidget::NullID;
720 if ( widget->parentID == GDLWidget::NullID )
721 return actID;
722 else
723 actID = widget->parentID;
724 }
725 }
726
727 /**
728 @brief content of theWxWidget has changed, make size changes appear if Dynamic property Set
729 */
RefreshDynamicWidget()730 void GDLWidget::RefreshDynamicWidget() {
731 if (this->IsDynamicResize()) {
732 if (theWxContainer && theWxContainer!=theWxWidget) {
733 wxPanel* p=static_cast<wxPanel*>(theWxContainer);
734 wxWindow* w=static_cast<wxWindow*>(theWxWidget);
735 if (p) {
736 wxSizer* s=p->GetSizer();
737 if (s) s->Fit(w); else p->Fit();
738 }
739 }
740 UpdateGui();
741 }
742 }
743
SendWidgetTimerEvent(DDouble secs)744 void GDLWidget::SendWidgetTimerEvent(DDouble secs) {
745 WidgetIDT* id = new WidgetIDT(widgetID);
746 int millisecs = floor(secs * 1000.0);
747 if (theWxWidget) { //we nee a handle on a wxWindow object...
748 wxWindow* w = dynamic_cast<wxWindow*> (theWxWidget);
749 assert(w != NULL);
750 w->GetEventHandler()->SetClientData(id);
751 if (m_windowTimer == NULL) {
752 m_windowTimer = new wxTimer(w->GetEventHandler(), widgetID);
753 }
754 #ifdef GDL_DEBUG_WIDGETS
755 std::cerr << "sending event," << widgetID << "," << m_windowTimer << std::endl;
756 #endif
757 m_windowTimer->StartOnce(millisecs);
758 }
759 }
760
ClearEvents()761 void GDLWidget::ClearEvents() {
762 if (!this->GetXmanagerActiveCommand()) eventQueue.Purge(this->GetWidgetID());
763 else readlineEventQueue.Purge(this->GetWidgetID());
764 }
765
HandleWidgetEvents()766 void GDLWidget::HandleWidgetEvents()
767 {
768 //make one loop for wxWidgets Events. Forcibly, as HandleWidgetEvents() is called by the readline eventLoop, we are in a non-blocked case.
769 #ifdef __WXMAC__
770 wxTheApp->Yield();
771 #else
772 wxGetApp().MainLoop(); //central loop for wxEvents!
773 #endif
774 //treat our GDL events...
775 DStructGDL* ev = NULL;
776 while( (ev = GDLWidget::readlineEventQueue.Pop()) != NULL)
777 {
778 // static int idIx = ev->Desc( )->TagIndex( "ID" ); // 0
779 // static int topIx = ev->Desc( )->TagIndex( "TOP" ); // 1
780 // static int handlerIx = ev->Desc( )->TagIndex( "HANDLER" ); // 2
781 // assert( idIx == 0 );
782 // assert( topIx == 1 );
783 // assert( handlerIx == 2 );
784
785 ev = CallEventHandler( ev );
786
787 if( ev != NULL)
788 {
789 int idIx = ev->Desc( )->TagIndex( "ID" );
790 assert( idIx == 0 );
791 WidgetIDT id = (*static_cast<DLongGDL*> (ev->GetTag( idIx, 0 )))[0];
792 Warning( "Unhandled event. ID: " + i2s( id ) );
793 GDLDelete( ev );
794 ev = NULL;
795 }
796 }
797 if (wxIsBusy()) wxEndBusyCursor( );
798 }
799
PushEvent(WidgetIDT baseWidgetID,DStructGDL * ev)800 void GDLWidget::PushEvent( WidgetIDT baseWidgetID, DStructGDL* ev) {
801 // Get XmanagerActiveCommand status
802 GDLWidget *baseWidget = GDLWidget::GetWidget( baseWidgetID );
803 if ( baseWidget != NULL ) {
804 bool xmanActCom = baseWidget->GetXmanagerActiveCommand( );
805 if ( !xmanActCom ) { //blocking: events in eventQueue.
806 // wxMessageOutputStderr().Printf(_T("eventQueue.Push: %d\n"),baseWidgetID);
807 eventQueue.PushBack( ev );
808 } else { //non-Blocking: events in readlineeventQueue.
809 // wxMessageOutputStderr().Printf(_T("readLineEventQueue.Push: %d\n"),baseWidgetID);
810 readlineEventQueue.PushBack( ev );
811 }
812 } else cerr << "NULL baseWidget (possibly Destroyed?) found in GDLWidget::PushEvent( WidgetIDT baseWidgetID=" << baseWidgetID << ", DStructGDL* ev=" << ev << "), please report!\n";
813 }
814
InformAuthorities(const std::string & message)815 void GDLWidget::InformAuthorities(const std::string& message){
816 // create GDL event struct
817 DStructGDL* ev = new DStructGDL( "*WIDGET_RUNTIME_ERROR*" );
818 ev->InitTag( "ID", DLongGDL( 0) );
819 ev->InitTag( "TOP", DLongGDL( 0 ) );
820 ev->InitTag( "HANDLER", DLongGDL( 0 ) );
821 ev->InitTag( "MESSAGE", DStringGDL(message) );
822 readlineEventQueue.PushFront( ev ); // push front (will be handled next)
823 }
824
GetXmanagerBlock()825 bool GDLWidget::GetXmanagerBlock()
826 {
827 bool xmanBlock = false;
828 WidgetListT::iterator it;
829 // (*it).first is widgetID
830 // (*it).second is pointer to widget
831
832 bool managed;
833 bool xmanActCom;
834
835 #ifdef GDL_DEBUG_WIDGETS
836 std::cout << "+ GetXmanagerBlock: widgetList:" << std::endl;
837 for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) {
838 std::cout << (*it).first << ": " << (*it).second->widgetID << " parentID: " <<
839 (*it).second->parentID << " uname: " << (*it).second->uName << std::endl;
840 }
841 std::cout << "- GetXmanagerBlock: widgetList end" << std::endl;
842 #endif
843 for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) {
844 // Only consider base widgets
845 if ( (*it).second->parentID == GDLWidget::NullID ) {
846 managed = (*it).second->GetManaged( );
847 xmanActCom = (*it).second->GetXmanagerActiveCommand( );
848 }
849 if ( managed && !xmanActCom ) {
850 xmanBlock = true;
851 break;
852 }
853 }
854 return xmanBlock;
855 }
GetNumberOfWidgets()856 DLong GDLWidget::GetNumberOfWidgets() {
857 WidgetListT::iterator it;
858 DLong result=0;
859 for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) result++;
860 return result;
861 }
GetWidgetsList()862 BaseGDL* GDLWidget::GetWidgetsList() {
863 DLong nw=GetNumberOfWidgets();
864 if (nw<=0) return new DLongGDL(0);
865 WidgetListT::iterator it;
866 SizeT index=0;
867 DLongGDL* result=new DLongGDL(nw,BaseGDL::NOZERO);
868 for ( it = widgetList.begin( ); it != widgetList.end( ); ++it ) {
869 (*result)[index]=(*it).second->widgetID; index++;
870 }
871 return result;
872 }
GetManagedWidgetsList()873 BaseGDL* GDLWidget::GetManagedWidgetsList() {
874 DLong nw=GetNumberOfWidgets();
875 if (nw<=0) return new DLongGDL(0);
876 WidgetListT::iterator it;
877 SizeT index;
878 for (index=0, it = widgetList.begin( ); it != widgetList.end( ); ++it ) {
879 if ((*it).second->GetManaged() == true) index++;
880 }
881 if (index<=0) return new DLongGDL(0);
882 DLongGDL* result=new DLongGDL(index,BaseGDL::NOZERO);
883 for (index=0, it = widgetList.begin( ); it != widgetList.end( ); ++it ) {
884 if ((*it).second->GetManaged() == true) (*result)[index++]=(*it).second->widgetID;
885 }
886 return result;
887 }
888
GetAllHeirs()889 DLongGDL* GDLWidget::GetAllHeirs(){
890 std::vector<WidgetIDT> widgetIDList;
891 std::vector<bool> has_children;
892 widgetIDList.push_back(this->widgetID);
893 if (this->NChildren() > 0) has_children.push_back(true);
894 else has_children.push_back(false);
895 //loop on this list, and add recursively all children when widget is a container.
896 SizeT currentVectorSize = widgetIDList.size();
897 while (1) {
898 for (SizeT i = 0; i < currentVectorSize; i++) {
899 if (has_children.at(i)) {
900 has_children.at(i) = false;
901 GDLWidget *widget = GDLWidget::GetWidget(widgetIDList.at(i));
902 DLongGDL* list = static_cast<GDLWidgetContainer*> (widget)->GetChildrenList();
903 for (SizeT j = 0; j < list->N_Elements(); j++) {
904 widgetIDList.push_back((*list)[j]);
905 if (GDLWidget::GetWidget((*list)[j])->NChildren() > 0) has_children.push_back(true);
906 else has_children.push_back(false);
907 }
908 }
909 }
910 if (widgetIDList.size() == currentVectorSize) break; //no changes
911 currentVectorSize = widgetIDList.size();
912 }
913 DLongGDL* result = new DLongGDL(currentVectorSize, BaseGDL::NOZERO);
914 for (SizeT i = 0; i < currentVectorSize ; ++i) (*result)[i] = widgetIDList[i];
915 return result;
916 }
917
918 //
InitWx()919 bool GDLWidget::InitWx()
920 { if (wxTheApp == NULL) { //not already initialized
921 if (!wxInitialize()) {
922 std::cerr << "WARNING: wxWidgets not initializing, widget-related commands will not be available." << std::endl;
923 return false;
924 }
925 } else {std::cerr << "INFO: wxWidgets already initialized (in 3rd party library?), pursue with fingers crossed" << std::endl; }
926 wxInitAllImageHandlers(); //do it here once for all
927 return true;
928 }
929 // Init
Init()930 void GDLWidget::Init()
931 {
932 //set system font to something sensible now that wx is ON:
933 if (forceWxWidgetsUglyFonts)
934 systemFont = wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL) ;// identical for me to GDLWidget::setDefaultFont(wxFont("Monospace 8"));
935 #if __WXMSW__ //update for windows:
936 bool ok=systemFont.SetNativeFontInfoUserDesc(wxString("consolas 8")); //consolas 8 is apparently the one most identical to linux courier 8 and IDL X11 default font.
937 if (!ok) systemFont = wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL) ;
938 #endif
939 else systemFont = *wxSMALL_FONT; // close to IDL in size, but nicer (not fixed).
940
941 //initially defaultFont and systemFont are THE SAME.
942 defaultFont=systemFont;
943 SetWxStarted();
944 //use a phantom window to retrieve th exact size of scrollBars wxWidget give wrong values.
945 gdlwxPhantomFrame* test = new gdlwxPhantomFrame();
946 test->Hide();
947 test->Realize();
948 test->Destroy();
949 //initialize default image lists for trees:
950 // Make an image list containing small icons
951 wxSize ImagesSize(DEFAULT_TREE_IMAGE_SIZE,DEFAULT_TREE_IMAGE_SIZE);
952 gdlDefaultTreeImages = new wxImageList(ImagesSize.x, ImagesSize.y, true);
953 //order must be same as enum definition!
954 gdlDefaultTreeImages->Add(wxArtProvider::GetBitmap(wxART_NORMAL_FILE, wxART_OTHER, ImagesSize)); //gdlWxTree_ITEM,/gdlWxTree_ITEM_SELECTED (IDL give the same image)
955 gdlDefaultTreeImages->Add(wxArtProvider::GetBitmap(wxART_FOLDER, wxART_OTHER, ImagesSize)); //gdlWxTree_FOLDER
956 gdlDefaultTreeImages->Add(wxArtProvider::GetBitmap(wxART_FOLDER_OPEN, wxART_OTHER, ImagesSize)); //gdlWxTree_FOLDER_OPEN
957
958 wxSize StateImageSize=wxIcon(pixmap_unchecked).GetSize(); //
959 gdlDefaultTreeStateImages = new wxImageList(StateImageSize.x, StateImageSize.y, true);
960 gdlDefaultTreeStateImages->Add(wxIcon(pixmap_unchecked)); //gdlWxTree_UNCHECKED
961 gdlDefaultTreeStateImages->Add(wxIcon(pixmap_checked)); //gdlWxTree_UNCHECKED
962 }
963 // UnInit
UnInit()964 void GDLWidget::UnInit() {
965 if (wxIsStarted()) {
966 WidgetListT::iterator it;
967 for (it = widgetList.begin(); it != widgetList.end(); ++it) {
968 GDLWidget* w = (*it).second;
969 if (w != NULL) delete w;
970 }
971 GDLWidget::HandleWidgetEvents();
972 // the following cannot be done: once unitialized, the wxWidgets library cannot be safely initilized again.
973 // wxUninitialize( );
974 delete gdlDefaultTreeImages;
975 delete gdlDefaultTreeStateImages;
976 UnsetWxStarted(); //reset handlersOk too.
977 }
978 }
979
ConnectToDesiredEvents()980 void GDLWidget::ConnectToDesiredEvents(){
981 wxWindow* w=dynamic_cast<wxWindow*>(theWxWidget);
982 assert (w!=NULL);
983 //connect to general events
984 w->Connect(widgetID, wxEVT_TIMER, wxTimerEventHandler(gdlwxFrame::OnWidgetTimer)); //always.
985 if ( eventFlags & GDLWidget::EV_TRACKING ) {
986 w->Connect(widgetID,wxEVT_ENTER_WINDOW, wxMouseEventHandler(gdlwxFrame::OnEnterWindow));
987 w->Connect(widgetID,wxEVT_LEAVE_WINDOW, wxMouseEventHandler(gdlwxFrame::OnLeaveWindow));
988 }
989 if ( eventFlags & GDLWidget::EV_CONTEXT ) w->Connect(widgetID,wxEVT_CONTEXT_MENU, wxContextMenuEventHandler(gdlwxFrame::OnContextEvent));
990 if ( eventFlags & GDLWidget::EV_KBRD_FOCUS ) {
991 w->Connect(widgetID,wxEVT_SET_FOCUS, wxFocusEventHandler(gdlwxFrame::OnKBRDFocusChange));
992 w->Connect(widgetID,wxEVT_KILL_FOCUS, wxFocusEventHandler(gdlwxFrame::OnKBRDFocusChange));
993 }
994 for (int i = 0; i < desiredEventsList.size(); ++i) {
995 desiredEventsList[i]->w->Connect(widgetID, desiredEventsList[i]->t, desiredEventsList[i]->f);
996 }
997 // useful to have no event yet produced at this stage?
998 // w->DeletePendingEvents();
999 }
1000
DisableSizeEvents(gdlwxFrame * & tlbFrame,WidgetIDT & id)1001 bool GDLWidget::DisableSizeEvents(gdlwxFrame* &tlbFrame,WidgetIDT &id) {
1002 GDLWidgetBase *tlb = this->GetMyTopLevelBaseWidget();
1003 tlbFrame = tlb->GetMyTopLevelFrame();
1004 id = tlb->GetWidgetID();
1005 bool disconnect = ((tlb->GetEventFlags() & GDLWidget::EV_SIZE) == GDLWidget::EV_SIZE);
1006 if (disconnect) tlbFrame->Disconnect(id, wxEVT_SIZE, gdlSIZE_EVENT_HANDLER);
1007 return disconnect;
1008 }
1009
EnableSizeEvents(gdlwxFrame * & tlbFrame,WidgetIDT & id)1010 void GDLWidget::EnableSizeEvents(gdlwxFrame* &tlbFrame,WidgetIDT &id) {
1011 if (tlbFrame) tlbFrame->Connect(id, wxEVT_SIZE, gdlSIZE_EVENT_HANDLER);
1012 }
1013 //initialize static member
1014 int GDLWidget::gdl_lastControlId=0;
1015
GDLWidget(WidgetIDT p,EnvT * e,BaseGDL * vV,DULong eventFlags_)1016 GDLWidget::GDLWidget( WidgetIDT p, EnvT* e, BaseGDL* vV, DULong eventFlags_)
1017 : theWxWidget( NULL )
1018 , theWxContainer(NULL)
1019 , widgetID (0)
1020 , parentID( p )
1021 , uValue( NULL )
1022 , vValue( vV )
1023 , scrolled(false)
1024 , sensitive(true)
1025 , managed( false )
1026 , eventFlags( eventFlags_ )
1027 , exclusiveMode( 0 )
1028 , wOffset(wxDefaultPosition)
1029 , wSize(wxDefaultSize)
1030 , wScreenSize(wxDefaultSize)
1031 , widgetSizer( NULL )
1032 , widgetPanel( NULL )
1033 , framePanel( NULL )
1034 , widgetType(GDLWidget::WIDGET_UNKNOWN)
1035 , widgetName("")
1036 , groupLeader(GDLWidget::NullID)
1037 , unitConversionFactor(wxRealPoint(1.0,1.0)) //no conversion at start.
1038 , frameWidth(0)
1039 , font(defaultFont)
1040 , valid(true)
1041 , alignment(gdlwALIGN_NOT)
1042 , widgetStyle(wxSTRETCH_NOT)
1043 , dynamicResize(0) //unset
1044 , eventFun("")
1045 , eventPro("")
1046 , killNotify("")
1047 , notifyRealize("")
1048 , proValue("")
1049 , funcValue("")
1050 , uName("")
1051 {
1052 m_windowTimer = NULL;
1053
1054 if ( e != NULL ) GetCommonKeywords( e ); else DefaultValuesInAbsenceofEnv();
1055
1056 // was widgetID = wxWindow::NewControlId( ); // but some scripts use the fact that widget ids are positive (graffer.pro)
1057 widgetID = GDLNewControlId( );
1058
1059 if ( parentID != GDLWidget::NullID ) {
1060
1061 GDLWidget* gdlParent = GetWidget( parentID );
1062 assert( gdlParent != NULL);
1063
1064 // a col or row sizer means no offset
1065 if (GetParentSizer()) wOffset=wxDefaultPosition;
1066 //there is a ParentID, so widgetPanel:
1067 widgetPanel=GetParentPanel();
1068
1069 if ( gdlParent->IsContainer( ) ) { //only case, include some buttons
1070 GDLWidgetContainer* base = dynamic_cast<GDLWidgetContainer*> (gdlParent);
1071 base->AddChildID( widgetID );
1072 }
1073 else if ( gdlParent->IsMenu( ) )
1074 {
1075 GDLWidgetMenu* menu = dynamic_cast<GDLWidgetMenu*> (gdlParent);
1076 if (menu) menu->AddChildID( widgetID );
1077 }
1078 else if ( gdlParent->IsMenuBar( ) )
1079 {
1080 GDLWidgetMenuBar* mb = dynamic_cast<GDLWidgetMenuBar*> (gdlParent);
1081 mb->AddChildID( widgetID );
1082 }
1083 // else if ( gdlParent->IsTree( ) )
1084 // {
1085 // // do nothing
1086 // }// else { assert(false);} //other widgets are parent of popups, assert should be removed.
1087 }
1088
1089 widgetList.insert( widgetList.end( ), std::pair<WidgetIDT, GDLWidget*>(widgetID, this) );
1090 #ifdef GDL_DEBUG_WIDGETS
1091 wxMessageOutputStderr( ).Printf( _T( "inserted: ID: %d parentID: %d\n" ), widgetID, parentID );
1092 #endif
1093 if (groupLeader != GDLWidget::NullID) {
1094 GDLWidget* leader=this->GetWidget(groupLeader);
1095 if (leader) leader->AddToFollowers(widgetID);
1096 }
1097 }
1098
SetSensitive(bool value)1099 void GDLWidget::SetSensitive(bool value)
1100 {
1101 sensitive = value;
1102 wxWindow *me=dynamic_cast<wxWindow*>(theWxWidget);
1103 if (me) {if (value) me->Enable(); else me->Disable();}
1104 }
1105
GetSensitive()1106 bool GDLWidget::GetSensitive()
1107 {
1108 return sensitive;
1109 }
1110
GetXmanagerActiveCommand()1111 bool GDLWidget::GetXmanagerActiveCommand() {
1112 GDLWidgetTopBase* w = GetMyTopLevelBaseWidget();
1113 return w->GetXmanagerActiveCommand();
1114 }
1115
GetSibling()1116 DLong GDLWidget::GetSibling()
1117 {
1118 if ( parentID == GDLWidget::NullID ) {return 0;}
1119 GDLWidget * parent=GetWidget(parentID);
1120 if (parent->IsContainer() || parent->IsMenuBar() || parent->IsMenu() || parent->IsTree()) {
1121 return parent->GetTheSiblingOf(widgetID);
1122 }
1123 return 0;
1124 }
SetFocus()1125 void GDLWidget::SetFocus() //gives focus to the CHILD of the panel.
1126 {
1127 wxWindow *me=dynamic_cast<wxWindow*>(this->GetWxWidget()); if (me!=NULL) me->SetFocus(); else cerr<<"Setting Focus for unknown widget!\n";
1128 }
SetWidgetPosition(DLong posx,DLong posy)1129 void GDLWidget::SetWidgetPosition(DLong posx, DLong posy){
1130 // -1: not set ---> keep the same
1131 wxWindow* me=static_cast<wxWindow*>(theWxContainer);
1132 if (me) {
1133 wxPoint where=me->GetPosition();
1134 if (posx >= 0) where.x=posx;
1135 if (posy >= 0) where.y=posy;
1136 me->Move(where);
1137 } else cerr<<"set offset on non-existent widget!"<<endl;
1138
1139 UPDATE_WINDOW;
1140
1141 }
1142
SetWidgetSize(DLong sizex,DLong sizey)1143 void GDLWidget::SetWidgetSize(DLong sizex, DLong sizey) //in pixels. Always.
1144 {
1145 START_CHANGESIZE_NOEVENT
1146
1147 //although 2 values are passed, one only may be set by the user.
1148 //the code is:
1149 // -1: not set --> keep the same
1150 // 0 : set, and means: do your best.
1151 // > 0 : imposed size.
1152
1153 //Sizes are in pixels. Units must be converted before calling this function.
1154 wxWindow* me=dynamic_cast<wxWindow*>(theWxWidget);
1155 if (me==NULL) {
1156 #ifdef GDL_DEBUG_WIDGETS
1157 wxMessageOutputStderr( ).Printf( _T( "GDLWidget::SetSize of non wxWindow %s\n"),this->GetWidgetName().c_str());
1158 #endif
1159 return;
1160 }
1161 //a graphic window cannot be larger than the base widget it is in, if the base widget size has been fixed
1162 wxSize currentSize=me->GetSize();
1163 wxSize currentBestSize=me->GetBestSize();
1164 #ifdef GDL_DEBUG_WIDGETS
1165 wxMessageOutputStderr( ).Printf( _T( "GDLWidget::SetSize currentSize=%d,%d (%s)\n"),currentSize.x,currentSize.y,this->GetWidgetName().c_str());
1166 #endif
1167 //unprecised sizes do not change
1168 if (sizex == -1) sizex = currentSize.x;
1169 if (sizey == -1) sizey = currentSize.y;
1170
1171 if (widgetSizer) {
1172 //passed zeroes = mr sizer, do your best..
1173 if (sizex == 0) sizex = -1;
1174 if (sizey == 0) sizey = -1;
1175 } else {
1176 //passed zeroes = your best is to keep best size (in cache, value defined at creation)
1177 if (sizex == 0) sizex = currentBestSize.x;
1178 if (sizey == 0) sizey = currentBestSize.y;
1179 }
1180 wSize.x = sizex;
1181 wSize.y = sizey;
1182 me->SetSize(wSize);
1183 //the sizer takes care of the eventual frame
1184 me->SetMinSize(wSize);
1185 //framed bases may have a complicated frame around, to be resized:
1186 if (theWxContainer != theWxWidget) {
1187 wxWindow* container = dynamic_cast<wxWindow*> (theWxContainer);
1188 wxSizer* s=me->GetSizer();
1189 if (s) s->Fit(me); else container->Fit();
1190 }
1191 UpdateGui();
1192
1193 END_CHANGESIZE_NOEVENT
1194
1195
1196 #ifdef GDL_DEBUG_WIDGETS
1197 wxMessageOutputStderr( ).Printf( _T( "GDLWidget::SetSize %d,%d (%s)\n"),sizex,sizey,this->GetWidgetName().c_str());
1198 #endif
1199 }
1200
SetWidgetScreenSize(DLong sizex,DLong sizey)1201 void GDLWidget::SetWidgetScreenSize(DLong sizex, DLong sizey) //in pixels. Always.
1202 {
1203 START_CHANGESIZE_NOEVENT
1204
1205 //although 2 values are passed, one only may be set by the user.
1206 //the code is:
1207 // -1: not set --> keep the same
1208 // 0 : set, and means: do your best.
1209 // > 0 : imposed size.
1210
1211 //Sizes are in pixels. Units must be converted before calling this function.
1212 wxWindow* me = dynamic_cast<wxWindow*> (theWxWidget);
1213 if (me == NULL) {
1214 #ifdef GDL_DEBUG_WIDGETS
1215 wxMessageOutputStderr().Printf(_T("GDLWidget::SetSize of non wxWindow %s\n"), this->GetWidgetName().c_str());
1216 #endif
1217 return;
1218 }
1219 //a graphic window cannot be larger than the base widget it is in, if the base widget size has been fixed
1220 wxSize currentSize = me->GetSize();
1221 wxSize currentBestSize = me->GetBestSize();
1222 #ifdef GDL_DEBUG_WIDGETS
1223 wxMessageOutputStderr().Printf(_T("GDLWidget::SetSize currentSize=%d,%d (%s)\n"), currentSize.x, currentSize.y, this->GetWidgetName().c_str());
1224 #endif
1225 //unprecised sizes do not change
1226 if (sizex == -1) sizex = currentSize.x;
1227 if (sizey == -1) sizey = currentSize.y;
1228
1229 if (widgetSizer) {
1230 //passed zeroes = mr sizer, do your best..
1231 if (sizex == 0) sizex = -1;
1232 if (sizey == 0) sizey = -1;
1233 } else {
1234 //passed zeroes = your best is to keep best size (in cache, value defined at creation)
1235 if (sizex == 0) sizex = currentBestSize.x;
1236 if (sizey == 0) sizey = currentBestSize.y;
1237 }
1238 wSize.x = sizex;
1239 wSize.y = sizey;
1240 me->SetSize(wSize); //includes scrollbars.
1241 //the sizer takes care of the eventual frame
1242 me->SetMinSize(wSize); //includes scrollbars.
1243 //framed bases may have a complicated frame around, to be resized:
1244 if (theWxContainer != theWxWidget) {
1245 wxWindow* container = dynamic_cast<wxWindow*> (theWxContainer);
1246 wxSizer* s = me->GetSizer();
1247 if (s) s->Fit(me);
1248 else container->Fit();
1249 }
1250 UpdateGui();
1251
1252 END_CHANGESIZE_NOEVENT
1253
1254
1255 #ifdef GDL_DEBUG_WIDGETS
1256 wxMessageOutputStderr().Printf(_T("GDLWidget::SetSize %d,%d (%s)\n"), sizex, sizey, this->GetWidgetName().c_str());
1257 #endif
1258 }
1259
SetBaseTitle(std::string & title_)1260 void GDLWidgetTabbedBase::SetBaseTitle(std::string &title_)
1261 {
1262 GDLWidgetTab* parentTab=dynamic_cast<GDLWidgetTab*>(this->GetMyParent());
1263 if (parentTab) {
1264 wxNotebook* wxParent = dynamic_cast<wxNotebook*> (parentTab->GetWxWidget( ));
1265 wxParent->SetPageText(wxParent->FindPage(static_cast<wxWindow*>(theWxWidget)),wxString(title_.c_str(), wxConvUTF8));
1266 }
1267 #ifdef GDL_DEBUG_WIDGETS
1268 else wxMessageOutputStderr( ).Printf( _T( "GDLWidgetTabbedBase::SetBaseTitle() no parent tab exists? %d\n"));
1269 #endif
1270 }
1271
~GDLWidgetTabbedBase()1272 GDLWidgetTabbedBase::~GDLWidgetTabbedBase()
1273 {
1274 #ifdef GDL_DEBUG_WIDGETS
1275 std::cout << "~GDLWidgetTabbedBase(" << widgetID << ")" << std::endl;
1276 #endif
1277 GDLWidgetTab* parentTab=static_cast<GDLWidgetTab*>(this->GetMyParent());
1278 if (parentTab) { //may be already destroyed.
1279 wxNotebook* wxParent = static_cast<wxNotebook*> (parentTab->GetWxWidget( ));
1280 //whereAmI?
1281 myPage=wxParent->FindPage(static_cast<wxWindow*>(theWxContainer));
1282 if (wxParent) wxParent->RemovePage(myPage); //do not delete the page, GDL will delete the contents itself, widget per widget.
1283 }
1284 #ifdef GDL_DEBUG_WIDGETS
1285 else wxMessageOutputStderr( ).Printf( _T( "~GDLWidgetTabbedBase() no parent tab exists? %d\n"));
1286 #endif
1287 }
1288
Realize(bool map,bool use_default)1289 void GDLWidget::Realize( bool map, bool use_default) { GetMyTopLevelBaseWidget()->Realize(map, use_default); }
1290
Realize(bool map,bool use_default)1291 void GDLWidgetTopBase::Realize(bool map, bool use_default) {
1292 #ifdef GDL_DEBUG_WIDGETS
1293 wxMessageOutputStderr().Printf(_T("GDLWidgetTopBase:Realize: %d\n"), widgetID);
1294 #endif
1295 if (use_default) map = GetMap();
1296
1297 OnRealize();
1298
1299 if (map) topFrame->Show() ; //endShowRequestEvent();
1300 else topFrame->Hide(); //SendHideRequestEvent();
1301 realized=true;
1302 }
1303
IsRealized()1304 bool GDLWidget::IsRealized() {
1305 GDLWidgetTopBase *tlb = GetMyTopLevelBaseWidget();
1306 gdlwxFrame* topFrame = tlb->GetTopFrame();
1307 return (tlb->IsTopLevelRealized());
1308 }
OnRealize()1309 void GDLWidgetContainer::OnRealize() {
1310 #ifdef GDL_DEBUG_WIDGETS
1311 wxMessageOutputStderr().Printf(_T("GDLWidgetContainer::OnRealize: %d\n"), widgetID);
1312 #endif
1313 //setFont() will set the font for this widget and children if FONT= is present in the WIDGET_XXX command (and is supported)
1314 this->setFont();
1315 this->SetSensitive(sensitive);
1316
1317 for (std::deque<WidgetIDT>::reverse_iterator c = children.rbegin(); c != children.rend(); ++c) {
1318 // for (std::deque<WidgetIDT>::iterator c = children.begin(); c != children.end(); ++c) {
1319 GDLWidget* w = GetWidget(*c);
1320 if (w != NULL)
1321 w->OnRealize();
1322 }
1323
1324 wxPanel* p=static_cast<wxPanel*> (theWxContainer);
1325 if (p) {
1326 wxSizer* s = p->GetSizer();
1327 if (s) s->Fit(p);
1328 else {
1329 p->Fit();
1330 if (this->GetParentSizer() == NULL) { //force size of parent since we cannot leave it to a nonexistent parent sizer.
1331 GDLWidgetContainer* myParentContainer = static_cast<GDLWidgetContainer*> (this->GetMyParentBaseWidget());
1332 if (myParentContainer != NULL) {
1333 wxWindow* w = static_cast<wxWindow*> (this->GetParentPanel());
1334 assert(w != NULL);
1335 wxSize wSize = w->GetSize();
1336 wxSize mySize = p->GetSize();
1337 // if w.x or w.y was SET BY USER it is a requested size, that we should not change
1338 wxSize desiredSize;
1339 if (myParentContainer->xFree()) desiredSize.x = max(mySize.x, wSize.x);
1340 else {
1341 desiredSize.x = wSize.x;
1342 }
1343 if (myParentContainer->yFree()) desiredSize.y = max(mySize.y, wSize.y);
1344 else {
1345 desiredSize.y = wSize.y;
1346 }
1347 w->SetSize(desiredSize);
1348 w->SetMinSize(desiredSize);
1349 }
1350 }
1351 }
1352 }
1353 #ifdef GDL_DEBUG_WIDGETS
1354 else wxMessageOutputStderr().Printf(_T("Unknown Container for (%s) widget ID %d\n"), widgetName, widgetID);
1355 #endif
1356
1357 if (notifyRealize != "") { //insure it is called once only for this.
1358 std::string note = notifyRealize;
1359 notifyRealize.clear();
1360 CallEventPro(note, new DLongGDL(widgetID));
1361 }
1362 //define Events Last (TBC).
1363 ConnectToDesiredEvents();
1364 }
1365
OnRealize()1366 void GDLWidgetMenu::OnRealize() {
1367 //setFont() will set the font for this widget and children if FONT= is present in the WIDGET_XXX command (and is supported)
1368 this->setFont();
1369 this->SetSensitive(sensitive);
1370
1371 //Menu children are menus or entries, *NOT* any widget.
1372 for (std::deque<WidgetIDT>::reverse_iterator c = children.rbegin(); c != children.rend(); ++c) {
1373 // for (std::deque<WidgetIDT>::iterator c = children.begin(); c != children.end(); ++c) {
1374 GDLWidgetMenu* w = dynamic_cast<GDLWidgetMenu*>(GetWidget(*c));
1375 if (w != NULL)
1376 w->OnRealize();
1377 }
1378
1379 if (notifyRealize != "") { //insure it is called once only for this.
1380 std::string note = notifyRealize;
1381 notifyRealize.clear();
1382 CallEventPro(note, new DLongGDL(widgetID));
1383 }
1384 }
1385
1386 #define GetSysC(x) { col=wxSystemSettings::GetColour(x); r=col.Red();g=col.Green();b=col.Blue(); (*val)[0]=r;(*val)[1]=g;(*val)[2]=b; }
getSystemColours()1387 BaseGDL * GDLWidget::getSystemColours()
1388 {
1389 DStructGDL* colo = new DStructGDL( "WIDGET_SYSTEM_COLORS");
1390 DIntGDL* val=new DIntGDL( dimension(3), BaseGDL::NOZERO);
1391 int r,g,b;
1392 wxColour col;
1393 GetSysC(wxSYS_COLOUR_3DDKSHADOW );
1394 colo->InitTag("DARK_SHADOW_3D",(*val));
1395 colo->InitTag("SHADOW_3D", (*val));
1396 GetSysC(wxSYS_COLOUR_3DLIGHT );
1397 colo->InitTag("FACE_3D", (*val));
1398 colo->InitTag("LIGHT_EDGE_3D", (*val));
1399 colo->InitTag("LIGHT_3D", (*val));
1400 GetSysC(wxSYS_COLOUR_ACTIVEBORDER );
1401 colo->InitTag("ACTIVE_BORDER", (*val));
1402 GetSysC(wxSYS_COLOUR_ACTIVECAPTION );
1403 colo->InitTag("ACTIVE_CAPTION", (*val));
1404 GetSysC(wxSYS_COLOUR_APPWORKSPACE );
1405 colo->InitTag("APP_WORKSPACE", (*val));
1406 GetSysC(wxSYS_COLOUR_DESKTOP );
1407 colo->InitTag("DESKTOP", (*val));
1408 GetSysC(wxSYS_COLOUR_BTNTEXT );
1409 colo->InitTag("BUTTON_TEXT", (*val));
1410 GetSysC(wxSYS_COLOUR_CAPTIONTEXT );
1411 colo->InitTag("CAPTION_TEXT", (*val));
1412 GetSysC(wxSYS_COLOUR_GRAYTEXT );
1413 colo->InitTag("GRAY_TEXT", (*val));
1414 GetSysC(wxSYS_COLOUR_HIGHLIGHT );
1415 colo->InitTag("HIGHLIGHT", (*val));
1416 GetSysC(wxSYS_COLOUR_HIGHLIGHTTEXT );
1417 colo->InitTag("HIGHLIGHT_TEXT", (*val));
1418 GetSysC(wxSYS_COLOUR_INACTIVEBORDER );
1419 colo->InitTag("INACTIVE_BORDER", (*val));
1420 GetSysC(wxSYS_COLOUR_INACTIVECAPTION );
1421 colo->InitTag("INACTIVE_CAPTION", (*val));
1422 GetSysC(wxSYS_COLOUR_INACTIVECAPTIONTEXT );
1423 colo->InitTag("INACTIVE_CAPTION_TEXT", (*val));
1424 GetSysC(wxSYS_COLOUR_INFOBK );
1425 colo->InitTag("TOOLTIP_BK", (*val));
1426 GetSysC(wxSYS_COLOUR_INFOTEXT );
1427 colo->InitTag("TOOLTIP_TEXT", (*val));
1428 GetSysC(wxSYS_COLOUR_MENU );
1429 colo->InitTag("MENU", (*val));
1430 GetSysC(wxSYS_COLOUR_MENUTEXT );
1431 colo->InitTag("MENU_TEXT", (*val));
1432 GetSysC(wxSYS_COLOUR_SCROLLBAR );
1433 colo->InitTag("SCROLLBAR", (*val));
1434 GetSysC(wxSYS_COLOUR_WINDOW );
1435 colo->InitTag("WINDOW_BK", (*val));
1436 GetSysC(wxSYS_COLOUR_WINDOWFRAME );
1437 colo->InitTag("WINDOW_FRAME", (*val));
1438 GetSysC(wxSYS_COLOUR_WINDOWTEXT );
1439 colo->InitTag("WINDOW_TEXT", (*val));
1440 return colo;
1441 }
1442
~GDLWidget()1443 GDLWidget::~GDLWidget()
1444 {
1445 #ifdef GDL_DEBUG_WIDGETS
1446 std::string state=(this->IsValid())?" ":"(Already destroyed) ";
1447 std::cout << "~GDLWidget "+state+"("<< widgetID <<")"<< std::endl;
1448 #endif
1449
1450 if (!this->IsValid()) return; //to avoid crashing if asserts are not honored
1451 //unvalidate widget to prevent some further actions
1452 this->SetUnValid();
1453 if (m_windowTimer) {if (m_windowTimer->IsRunning()) m_windowTimer->Stop();}
1454
1455 // call KILL_NOTIFY procedures
1456 this->OnKill();
1457
1458 // kill followers (here?)
1459 // delete all followers (in reverse order ?)
1460 while (!followers.empty()) {
1461 #ifdef GDL_DEBUG_WIDGETS
1462 std::cout << "~GDLWidget("<< widgetID <<"): destroy follower "<< followers.back()<< endl;
1463 #endif
1464 GDLWidget* follower=GetWidget(followers.back()); followers.pop_back();
1465 if (follower) delete follower;
1466 }
1467
1468 GDLWidget* gdlParent = GetMyParent();
1469 if (gdlParent) { //not the TLB
1470 gdlParent->RemoveIfFollower(widgetID);
1471
1472 // UpdateGui(); //way too long! use a more subtle command!
1473
1474 } else {
1475 static_cast<GDLWidgetTopBase*>(this)->GetTopFrame()->Hide();
1476 static_cast<GDLWidgetTopBase*>(this)->GetTopFrame()->Destroy(); //delete topBase
1477 }
1478
1479 GDLDelete(uValue);
1480 GDLDelete(vValue);
1481 uName.clear();
1482 proValue.clear();
1483 funcValue.clear();
1484 eventPro.clear(); // event handler PRO
1485 eventFun.clear(); // event handler FUN
1486 notifyRealize.clear();
1487 killNotify.clear();
1488 valid=false; //if not, is in the process of being destroyed (prevent reentrance).
1489
1490 widgetList.erase(widgetID);
1491 desiredEventsList.clear();
1492 followers.clear();
1493 widgetName.clear();
1494
1495 theWxContainer=NULL;
1496 theWxWidget=NULL;
1497 widgetSizer=NULL;
1498 widgetPanel=NULL;
1499 framePanel=NULL;
1500 }
1501
Raise()1502 void GDLWidget::Raise()
1503 {
1504 this->GetMyTopLevelFrame()->Raise();
1505 }
1506
Lower()1507 void GDLWidget::Lower()
1508 {
1509 this->GetMyTopLevelFrame()->Lower();
1510 }
1511
GetGeometry(wxRealPoint fact)1512 DStructGDL* GDLWidget::GetGeometry(wxRealPoint fact)
1513 {
1514 if (!this->IsRealized()) this->Realize(true,false);//necessary if a geometry request is done previous to the command widget_control,xxx,,/Realize !
1515 GDLWidgetBase* container = static_cast<GDLWidgetBase*> (this->GetMyParent());
1516 assert(container != NULL);
1517 int ixsize = 0, iysize = 0, iscr_xsize = 0, iscr_ysize = 0;
1518 DFloat xsize = 0;
1519 DFloat ysize = 0;
1520 DFloat scr_xsize = 0;
1521 DFloat scr_ysize = 0;
1522 DFloat xoffset = 0;
1523 DFloat yoffset = 0;
1524 DFloat margin = 0;
1525
1526 DStructGDL* ex = new DStructGDL("WIDGET_GEOMETRY");
1527
1528 wxWindow* test = dynamic_cast<wxWindow*> (theWxContainer);
1529 if (test==NULL) return ex;
1530 wxRect r=test->GetRect();
1531 // std::cerr<<"CONTAINER: x: "<<r.x<<", y: "<<r.y<<", width="<<r.width<<", height="<<r.height<<std::endl;
1532 xoffset = r.x ;
1533 yoffset = r.y ;
1534 wxWindow* w = dynamic_cast<wxWindow*> (theWxWidget);
1535 if (w==NULL) return ex;
1536 wxRect z=w->GetRect();
1537 // std::cerr<<"WIDGET: x: "<<z.x<<", y: "<<z.y<<", width="<<z.width<<", height="<<z.height<<std::endl;
1538
1539 iscr_xsize = z.width;
1540 iscr_ysize = z.height;
1541 wxSize s=w->GetClientSize();
1542 ixsize = s.x; if (ixsize < 1) ixsize=iscr_xsize; //Patch for OSX where s.x is 0
1543 iysize = s.y; if (iysize < 1) iysize=iscr_ysize; //Patch for OSX where s.y is 0
1544
1545 if (theWxWidget == theWxContainer) margin=0; else {
1546 margin=(r.width-z.width)/2; //Rect is about the container, which is the widgetPanel and not the frame depending on case.
1547 }
1548
1549 if (this->IsInCharacters()) {
1550 wxSize fontSize = getFontSize();
1551 xsize = ixsize / fontSize.x;
1552 ysize = iysize / fontSize.y;
1553 } else {
1554 //size is in pixels, pass in requested units (1.0 default)
1555 xsize = ixsize / fact.x;
1556 ysize = iysize / fact.y;
1557 }
1558 scr_xsize = iscr_xsize / fact.x;
1559 scr_ysize = iscr_ysize / fact.y;
1560 xoffset /= fact.x;
1561 yoffset /= fact.y;
1562 margin /= fact.x;
1563
1564 ex->InitTag("XOFFSET", DFloatGDL(xoffset));
1565 ex->InitTag("YOFFSET", DFloatGDL(yoffset));
1566 ex->InitTag("XSIZE", DFloatGDL(xsize));
1567 ex->InitTag("YSIZE", DFloatGDL(ysize));
1568 ex->InitTag("SCR_XSIZE", DFloatGDL(scr_xsize));
1569 ex->InitTag("SCR_YSIZE", DFloatGDL(scr_ysize));
1570 ex->InitTag("MARGIN", DFloatGDL(margin));
1571 //special DRAW:
1572 if (this->IsDraw()) {
1573 wxSize d=w->GetVirtualSize();
1574 DFloat dxsize=d.x;
1575 DFloat dysize=d.y;
1576 ex->InitTag("DRAW_XSIZE", DFloatGDL(dxsize/fact.x));
1577 ex->InitTag("DRAW_YSIZE", DFloatGDL(dysize/fact.y));
1578 }
1579
1580 return ex;
1581 }
1582
GDLWidgetContainer(WidgetIDT parentID,EnvT * e,ULong eventFlags_)1583 GDLWidgetContainer::GDLWidgetContainer( WidgetIDT parentID, EnvT* e, ULong eventFlags_)
1584 : GDLWidget( parentID, e, NULL, eventFlags_),xfree(true),yfree(true)
1585 {
1586 }
1587
~GDLWidgetContainer()1588 GDLWidgetContainer::~GDLWidgetContainer()
1589 {
1590 #ifdef GDL_DEBUG_WIDGETS
1591 std::cout << "~GDLWidgetContainer(" << widgetID <<")"<< std::endl;
1592 #endif
1593
1594 // delete all children (in reverse order ?)
1595 while (!children.empty()) {
1596 GDLWidget* child=GetWidget(children.back()); children.pop_back();
1597
1598 if (child) {
1599 #ifdef GDL_DEBUG_WIDGETS
1600 std::cout << "~GDLWidgetContainer, deleting child ID #" << child->GetWidgetID() << " of container #" << widgetID << std::endl;
1601 #endif
1602 //special case for WIDGET_DRAW: delete from 'wdelete' command-like:
1603 if (child->IsDraw()) {
1604 gdlwxGraphicsPanel* draw=static_cast<gdlwxGraphicsPanel*>(child->GetWxWidget());
1605 draw->DeleteUsingWindowNumber(); //just emit quivalent to "wdelete,winNum".
1606 } else delete child;
1607 }
1608 }
1609
1610 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy(); //which is the panel.
1611 }
1612
1613 #ifdef PREFERS_MENUBAR
~GDLWidgetMenuBar()1614 GDLWidgetMenuBar::~GDLWidgetMenuBar() {
1615 #ifdef GDL_DEBUG_WIDGETS
1616 std::cout << "~GDLWidgetMenuBar(" << widgetID << ")" << std::endl;
1617 #endif
1618
1619 // delete all children (in reverse order ?)
1620 while (!children.empty()) {
1621 GDLWidget* child=GetWidget(children.back()); children.pop_back();
1622 if (child) {
1623 #ifdef GDL_DEBUG_WIDGETS
1624 std::cout << "~GDLWidgetMenuBar, deleting child ID #" << child->GetWidgetID() << " of container #" << widgetID << std::endl;
1625 #endif
1626 delete child;
1627 }
1628 }
1629 //remove wxWidgets MBAR from wxFrame container otherwise wxFrame will attempt to destroy it again and segfault
1630 dynamic_cast<wxMenuBar*> (theWxWidget)->GetFrame()->SetMenuBar(NULL);
1631 }
1632 #else
~GDLWidgetMenuBar()1633 GDLWidgetMenuBar::~GDLWidgetMenuBar() {
1634 #ifdef GDL_DEBUG_WIDGETS
1635 std::cout << "~GDLWidgetMenuBar(" << widgetID << ")" << std::endl;
1636 #endif
1637
1638 // delete all children (in reverse order ?)
1639 while (!children.empty()) {
1640 GDLWidget* child=GetWidget(children.back()); children.pop_back();
1641 if (child) {
1642 #ifdef GDL_DEBUG_WIDGETS
1643 std::cout << "~GDLWidgetMenuBar, deleting child ID #" << child->GetWidgetID() << " of container #" << widgetID << std::endl;
1644 #endif
1645 delete child;
1646 }
1647 }
1648 //toolbar can be removed
1649 dynamic_cast<wxToolBar*> (theWxWidget)->Destroy();
1650 }
1651 #endif
1652 /*********************************************************/
1653 // for WIDGET_BASE
1654 /*********************************************************/
GDLWidgetBase(WidgetIDT parentID,EnvT * e,ULong eventFlags_,bool mapWid,DLong col,DLong row,int exclusiveMode_,const DString & resource_name,const DString & rname_mbar,const DString & title_,const DString & display_name,int xpad_,int ypad_,DLong x_scroll_size,DLong y_scroll_size,bool grid_layout,long children_alignment,int space_)1655 GDLWidgetBase::GDLWidgetBase(WidgetIDT parentID, EnvT* e, ULong eventFlags_,
1656 bool mapWid,
1657 DLong col, DLong row,
1658 int exclusiveMode_,
1659 const DString& resource_name, const DString& rname_mbar,
1660 const DString& title_,
1661 const DString& display_name,
1662 int xpad_, int ypad_,
1663 DLong x_scroll_size, DLong y_scroll_size, bool grid_layout, long children_alignment, int space_)
1664 : GDLWidgetContainer(parentID, e, eventFlags_)
1665 , lastRadioSelection(NullID)
1666 , nrows(row)
1667 , ncols(col)
1668 , grid(grid_layout)
1669 , childrenAlignment(children_alignment)
1670 , space(space_)
1671 , xpad(xpad_)
1672 , ypad(ypad_)
1673 , doMap(mapWid) {
1674 // All bases can receive events: EV_CONTEXT, EV_KBRD_FOCUS, EV_TRACKING
1675
1676 wSize = computeWidgetSize();
1677 //get immediately rid of scroll sizes in case of scroll or not... Here is the logic:
1678
1679 if (x_scroll_size > 0) {scrolled=true;x_scroll_size*=unitConversionFactor.x;x_scroll_size+=gdlSCROLL_WIDTH_Y;}
1680 if (y_scroll_size > 0) {scrolled=true;y_scroll_size*=unitConversionFactor.y;y_scroll_size+=gdlSCROLL_HEIGHT_X;}
1681 if (scrolled) {
1682 if (x_scroll_size < 1) x_scroll_size = gdlDEFAULT_XSIZE+gdlSCROLL_WIDTH_Y;
1683 if (y_scroll_size < 1) y_scroll_size = gdlDEFAULT_YSIZE+gdlSCROLL_HEIGHT_X;
1684 }
1685 wScrollSize = scrolled ? wxSize(x_scroll_size , y_scroll_size ) : wSize; //y_scroll_size + gdlSCROLL_HEIGHT_X);
1686 xfree=(wScrollSize.x <= 0);
1687 yfree=(wScrollSize.y <= 0);
1688 // Set exclusiveMode
1689 // If exclusive then set to -1 to signal first radiobutton
1690 if ( exclusiveMode_ == BGEXCLUSIVE )
1691 this->SetExclusiveMode( BGEXCLUSIVE1ST );
1692 else
1693 this->SetExclusiveMode( exclusiveMode_ );
1694
1695 // COLUMN is default if col=0 and row=0 for exclusive etc bases.
1696 if ( this->GetExclusiveMode() != BGNORMAL ) {
1697 if (ncols < 1 && nrows <1 ) ncols=1;
1698 }
1699
1700 }
1701
1702 // generic creation of a base in which widgets will be put.
1703 //
1704 // defines widgetPanel which is the (scrolled) panel in which children will be Added.
1705 // widgetPanel may be a panel inside a (scrolled) panel used to mimic padding if necessary. In ths case it is the padding panel that is scrolled.
1706 // Further, all this casn be inside a frame.
1707 //
1708 // define the widgetSizer, the sizer that children will 'obey' (that will govern overall placement and size of children)
1709 // the widgetSizer may be NULL, in which case the placement of children inside the panel will be governed by their respective size and position,
1710 // but if widgetSizer exist, then everytime a new child is created, it must be invoked to resize/reposition this child.
1711 //
CreateBase(wxWindow * parent)1712 void GDLWidgetBase::CreateBase(wxWindow* parent){
1713 //the container is as ScrollPanel
1714 bool doFrame=true; //!(this->IsTopBase()); //IDL Prevents topBases to be framed (?).
1715 if (doFrame && frameWidth > 0) {
1716 wxScrolled<wxPanel>* frame = new wxScrolled<wxPanel>(parent, wxID_ANY, wOffset, wxDefaultSize, gdlBORDER_EXT);
1717 theWxContainer=frame;
1718 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
1719 frame->SetBackgroundColour(wxColour(0x60, 0xe0, 0x94)); //vert clair
1720 #endif
1721 wxBoxSizer* panelsz = new wxBoxSizer(wxVERTICAL);
1722 frame->SetSizer(panelsz);
1723 // Fancy variant:
1724 // int mode = wxBORDER_NONE;
1725 // int width = 2; //the size of wxBORDER_SUNKEN
1726 // if (frameWidth > 2) {
1727 // mode = wxBORDER_SIMPLE;
1728 // width = 3;
1729 // }
1730 // if (frameWidth > 3) {
1731 // mode = wxBORDER_RAISED;
1732 // width = 4;
1733 // }
1734 // wxPanel* frame_inside = new wxPanel(frame, wxID_ANY, wxDefaultPosition, wxDefaultSize, mode);
1735 // sz->Add(frame_inside, FRAME_ALLOWSTRETCH, wxALL, frameWidth - width);
1736 //
1737 // wxBoxSizer* sz_inside = new wxBoxSizer(wxVERTICAL);
1738 // frame_inside->SetSizer(sz_inside);
1739 // widgetPanel = new wxScrolledWindow(frame_inside, wxID_ANY, wOffset, wxDefaultSize);
1740 if (xpad > 0 || ypad > 0) {
1741 wxScrolled<wxPanel>* padxpady = new wxScrolled<wxPanel>(frame);
1742 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
1743 padxpady->SetBackgroundColour(wxColour(0xa7, 0x3d, 0x0f)); //orange fonce
1744 #endif
1745 wxGridBagSizer* sz = new wxGridBagSizer(ypad, xpad);
1746 padxpady->SetSizer(sz);
1747 sz->SetEmptyCellSize(wxSize(0, 0));
1748 if (xpad > 1) sz->Add(0, 0, wxGBPosition(1, 2));
1749 if (ypad > 1) sz->Add(0, 0, wxGBPosition(2, 1));
1750
1751 widgetPanel = new wxScrolledWindow(padxpady, widgetID, wOffset, wxDefaultSize);
1752 sz->Add(widgetPanel, wxGBPosition(1, 1));
1753 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
1754 widgetPanel->SetBackgroundColour(RandomWxColour());
1755 #endif
1756 // widgetPanel->SetVirtualSize(wSize);
1757 padxpady->SetSize(wScrollSize);
1758 padxpady->SetMinSize(wScrollSize);
1759 //Just Enable scrollBars if scrolling is necessary
1760 if (scrolled) {
1761 padxpady->SetScrollbars(gdlSCROLL_RATE, gdlSCROLL_RATE, wSize.x / gdlSCROLL_RATE, wSize.y / gdlSCROLL_RATE);
1762 padxpady->ShowScrollbars(wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS);
1763 }
1764 panelsz->Add(padxpady, FRAME_ALLOWSTRETCH, wxALL | wxEXPAND, frameWidth);//gdlFRAME_MARGIN);
1765 panelsz->Fit(padxpady);
1766 } else {
1767 widgetPanel = new wxScrolledWindow(frame, widgetID, wOffset, wxDefaultSize);
1768 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
1769 widgetPanel->SetBackgroundColour(RandomWxColour());
1770 #endif
1771 // widgetPanel->SetVirtualSize(wSize);
1772 widgetPanel->SetSize(wScrollSize);
1773 widgetPanel->SetMinSize(wScrollSize);
1774 //Just Enable scrollBars if scrolling is necessary
1775 if (scrolled) {
1776 widgetPanel->SetScrollbars(gdlSCROLL_RATE, gdlSCROLL_RATE, wSize.x / gdlSCROLL_RATE, wSize.y / gdlSCROLL_RATE);
1777 widgetPanel->ShowScrollbars(wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS);
1778 }
1779 panelsz->Add(widgetPanel, FRAME_ALLOWSTRETCH, wxALL | wxEXPAND, frameWidth);//gdlFRAME_MARGIN);
1780 panelsz->Fit(widgetPanel);
1781 }
1782 theWxWidget = widgetPanel;
1783 } else {
1784 if (xpad > 0 || ypad > 0 ) {
1785 wxScrolled<wxPanel>* padxpady = new wxScrolled<wxPanel>(parent);
1786 theWxContainer = padxpady;
1787 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
1788 padxpady->SetBackgroundColour(wxColour(0xa7, 0x3d, 0x0f)); //orange fonce
1789 #endif
1790 wxGridBagSizer* sz = new wxGridBagSizer(ypad, xpad);
1791 padxpady->SetSizer(sz);
1792 sz->SetEmptyCellSize(wxSize(0, 0));
1793 if (xpad > 1) sz->Add(0, 0, wxGBPosition(1, 2));
1794 if (ypad > 1) sz->Add(0, 0, wxGBPosition(2, 1));
1795
1796 widgetPanel = new wxScrolledWindow(padxpady, widgetID, wOffset, wxDefaultSize);
1797 sz->Add(widgetPanel, wxGBPosition(1, 1));
1798 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
1799 widgetPanel->SetBackgroundColour(RandomWxColour());
1800 #endif
1801 // widgetPanel->SetVirtualSize(wSize);
1802 padxpady->SetSize(wScrollSize);
1803 padxpady->SetMinSize(wScrollSize);
1804 //Just Enable scrollBars if scrolling is necessary
1805 if (scrolled) {
1806 padxpady->SetScrollbars(gdlSCROLL_RATE, gdlSCROLL_RATE, wSize.x / gdlSCROLL_RATE, wSize.y / gdlSCROLL_RATE);
1807 padxpady->ShowScrollbars(wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS);
1808 }
1809 } else {
1810 widgetPanel = new wxScrolledWindow(parent, widgetID, wOffset, wxDefaultSize);
1811 theWxContainer = widgetPanel;
1812 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
1813 widgetPanel->SetBackgroundColour(RandomWxColour());
1814 #endif
1815 // widgetPanel->SetVirtualSize(wSize);
1816 widgetPanel->SetSize(wScrollSize);
1817 widgetPanel->SetMinSize(wScrollSize);
1818 //Just Enable scrollBars if scrolling is necessary
1819 if (scrolled) {
1820 widgetPanel->SetScrollbars(gdlSCROLL_RATE, gdlSCROLL_RATE, wSize.x / gdlSCROLL_RATE, wSize.y / gdlSCROLL_RATE);
1821 widgetPanel->ShowScrollbars(wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS);
1822 }
1823 }
1824
1825 theWxWidget = widgetPanel;
1826 }
1827
1828
1829 //define inside sizer.
1830 widgetSizer = AddABaseSizer(ncols, nrows, grid, space);
1831 if (widgetSizer) widgetPanel->SetSizer(widgetSizer);
1832
1833 wxSizer* parentSizer = parent->GetSizer();
1834 if (parentSizer) parentSizer->Add(static_cast<wxWindow*>(theWxContainer), DONOTALLOWSTRETCH, wxALL | widgetAlignment(), gdlSPACE);
1835 }
1836
SetWidgetSize(DLong sizex,DLong sizey)1837 void GDLWidgetBase::SetWidgetSize(DLong sizex, DLong sizey)
1838 {
1839 START_CHANGESIZE_NOEVENT
1840
1841 wxWindow* me=dynamic_cast<wxWindow*>(theWxWidget);
1842 if (me==NULL) {
1843 #ifdef GDL_DEBUG_WIDGETS
1844 wxMessageOutputStderr( ).Printf( _T( "GDLWidget::SetSize of non wxWindow %s\n"),this->GetWidgetName().c_str());
1845 #endif
1846 return;
1847 }
1848 //a graphic window cannot be larger than the base widget it is in, if the base widget size has been fixed
1849 wxSize currentVirtualSize=me->GetVirtualSize();
1850 wxSize currentSize=me->GetSize();
1851 #ifdef GDL_DEBUG_WIDGETS
1852 wxMessageOutputStderr( ).Printf( _T( "GDLWidgetBase::SetSize currentSize=%d,%d\n"),currentSize.x,currentSize.y);
1853 #endif
1854
1855 if (widgetSizer) {
1856 //passed zeroes = mr sizer, do your best..
1857 if (sizex == 0) sizex = -1;
1858 if (sizey == 0) sizey = -1;
1859 } else {
1860 //passed zeroes = your best is to keep best size (in cache, value defined at creation)
1861 if (sizex == 0) sizex = scrolled?currentSize.x:currentVirtualSize.x;
1862 if (sizey == 0) sizey = scrolled?currentSize.y:currentVirtualSize.y;
1863 }
1864 wxSize theSize=wxSize(sizex,sizey);
1865 if (scrolled) theSize += wxSize(gdlSCROLL_HEIGHT_X, gdlSCROLL_WIDTH_Y);
1866 me->SetSize( theSize );
1867
1868 //framed bases may have a complicated frame around, to be resized:
1869 if (theWxContainer != theWxWidget) { //framed -> has a sizer
1870 wxWindow* container=dynamic_cast<wxWindow*>(theWxContainer);
1871 wxWindow* contained=dynamic_cast<wxWindow*>(theWxWidget);
1872 container->GetSizer()->Fit(contained);
1873 }
1874
1875 UPDATE_WINDOW;
1876
1877 END_CHANGESIZE_NOEVENT
1878
1879 #ifdef GDL_DEBUG_WIDGETS
1880 wxMessageOutputStderr( ).Printf( _T( "GDLWidgetBase::SetSize %d,%d (%s)\n"),sizex,sizey,this->GetWidgetName().c_str());
1881 #endif
1882 }
1883 /*********************************************************/
1884 // special TOP WIDGET_BASE
1885 /*********************************************************/
1886
GDLWidgetTopBase(EnvT * e,ULong eventFlags_,bool mapWid,WidgetIDT & mBarIDInOut,bool modal_,DLong frame_attr,DLong col,DLong row,int exclusiveMode_,bool floating,const DString & resource_name,const DString & rname_mbar,const DString & title_,const DString & display_name,int xpad_,int ypad_,DLong x_scroll_size,DLong y_scroll_size,bool grid_layout,long children_alignment,int space_)1887 GDLWidgetTopBase::GDLWidgetTopBase( EnvT* e, ULong eventFlags_,
1888 bool mapWid,
1889 WidgetIDT& mBarIDInOut, bool modal_, DLong frame_attr,
1890 DLong col, DLong row,
1891 int exclusiveMode_,
1892 bool floating,
1893 const DString& resource_name, const DString& rname_mbar,
1894 const DString& title_,
1895 const DString& display_name,
1896 int xpad_, int ypad_,
1897 DLong x_scroll_size, DLong y_scroll_size, bool grid_layout, long children_alignment, int space_)
1898 : GDLWidgetBase( GDLWidget::NullID, e, eventFlags_, mapWid, col, row, exclusiveMode_, resource_name, rname_mbar, title_, display_name, xpad_, ypad_, x_scroll_size, y_scroll_size, grid_layout, children_alignment, space_)
1899 , mbarID(mBarIDInOut)
1900 , xmanActCom(false)
1901 , modal(modal_)
1902 , realized(false)
1903 {
1904
1905 // All bases can receive events: EV_CONTEXT, EV_KBRD_FOCUS, EV_TRACKING
1906
1907 //on wxMAC, frame will not appear if style is not exactly this (!!!)
1908 #ifdef __WXMAC__
1909 long style = (wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxCAPTION | wxCLOSE_BOX);
1910 #else
1911 long style=wxDEFAULT_FRAME_STYLE|wxFRAME_TOOL_WINDOW; //wxFRAME_TOOL_WINDOW to NOT get focus. See behaviour of 'P' (photometry) while using ATV (atv.pro).
1912 if (frame_attr) {
1913 style=0;
1914 if (!(frame_attr & 1)) style |= (wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER| wxCAPTION);
1915 if (!(frame_attr & 2)) style |=wxSYSTEM_MENU;
1916 if (!(frame_attr & 4)) style |=wxCAPTION;
1917 if (!(frame_attr & 8)) style |=wxCLOSE_BOX;
1918 //style 16 not supported.
1919 }
1920 if (floating) {
1921 if (this->GetWidget(groupLeader)==NULL) e->Throw("FLOATING top level bases must have a group leader specified.");
1922 style |= wxFRAME_TOOL_WINDOW|wxSTAY_ON_TOP ; //wxFRAME_FLOAT_ON_PARENT will destroy the parent widget!!
1923 }
1924 #endif
1925
1926 // Top Level Base Widget: can receive special events: tlb_size, tlb_move, tlb_icon and tlb_kill. cannot be framed.
1927 wxString titleWxString;
1928 if (title_.size() < 1) titleWxString = wxString("GDL");
1929 else titleWxString = wxString(title_.c_str(), wxConvUTF8);
1930 if (floating) {
1931 wxWindow* parent=static_cast<wxWindow*>(this->GetWidget(groupLeader)->GetWxWidget());
1932 //make it really above parent:
1933 wxRect x=parent->GetScreenRect();
1934 if (wOffset.x < 0) wOffset.x =x.x+x.width/2;
1935 if (wOffset.y < 0) wOffset.y =x.y+x.height/2;
1936 }
1937 topFrame = new gdlwxFrame(NULL, this, widgetID, titleWxString, wOffset, wxDefaultSize, style);
1938 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
1939 topFrame->SetBackgroundColour(wxColour(0x81, 0x46, 0xf1)); //violet
1940 #endif
1941
1942 //Base Frame inherits default font -- then each widget will possibly get its own font when /FONT is possible
1943 topFrame->SetFont(defaultFont);
1944
1945 if (mbarID != 0) {
1946 #if PREFERS_MENUBAR
1947 GDLWidgetMenuBar* mBar = new GDLWidgetMenuBar(widgetID, e);
1948 mbarID = mBar->GetWidgetID();
1949 mBarIDInOut = mbarID;
1950 wxMenuBar* me = dynamic_cast<wxMenuBar*> (mBar->GetWxWidget());
1951 if (me) topFrame->SetMenuBar(me);
1952 else cerr << "Warning: GDLWidgetBase::GDLWidgetBase: Non-existent menubar widget!\n";
1953 #else
1954 GDLWidgetMenuBar* mBar = new GDLWidgetMenuBar(topFrame, widgetID, e);
1955 mbarID = mBar->GetWidgetID();
1956 mBarIDInOut = mbarID;
1957 #endif
1958 }
1959 wxSizer* tfSizer=new wxBoxSizer(wxVERTICAL);
1960 topFrame->SetSizer(tfSizer);
1961 CreateBase(topFrame); //define widgetPanel, widgetSizer, theWxWidget and theWxContainer.
1962 //it is the FRAME that manage all events. Here we dedicate particularly the tlb_* events:
1963 // note that we have the choice for Size Event Handler for Frames, but need to change also is widgets.cpp
1964 if (eventFlags & GDLWidget::EV_SIZE) this->AddToDesiredEvents(wxEVT_SIZE, gdlSIZE_EVENT_HANDLER, topFrame); //this->AddToDesiredEvents(wxEVT_SIZE, wxSizeEventHandler(GDLFrame::OnSizeWithTimer),topFrame);
1965 if (eventFlags & GDLWidget::EV_MOVE) this->AddToDesiredEvents(wxEVT_MOVE, wxMoveEventHandler(gdlwxFrame::OnMove), topFrame);
1966 if (eventFlags & GDLWidget::EV_ICONIFY) this->AddToDesiredEvents(wxEVT_ICONIZE, wxIconizeEventHandler(gdlwxFrame::OnIconize), topFrame);
1967 if (eventFlags & GDLWidget::EV_KILL) {
1968 this->AddToDesiredEvents(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(gdlwxFrame::OnCloseFrame), topFrame);
1969 } else {
1970 this->AddToDesiredEvents(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(gdlwxFrame::OnUnhandledCloseFrame), topFrame);
1971 }
1972 this->AddToDesiredEvents(wxEVT_SHOW_REQUEST, wxCommandEventHandler(gdlwxFrame::OnShowRequest), topFrame);
1973 this->AddToDesiredEvents(wxEVT_HIDE_REQUEST, wxCommandEventHandler(gdlwxFrame::OnShowRequest), topFrame);
1974 //UPDATE_WINDOW; REALIZE_IF_NEEDED //no use here
1975 //this->Realize(false);
1976 }
1977
widgetAlignment()1978 inline int GDLWidgetTopBase::widgetAlignment() {
1979 long myAlign = alignment;
1980 //there is no parent for topBase...
1981 // if (myAlign == gdlwALIGN_NOT) {
1982 // myAlign = this->GetMyParentBaseWidget()->getChildrenAlignment();
1983 // }
1984 //wxALIGN_LEFT and TOP is in fact wxALIGN_NOT as this is the default alignment
1985 if (myAlign == gdlwALIGN_NOT) return wxALIGN_CENTER;
1986 //left is top by default and right is bottom. So define left as top and remove top if bottom, etc.
1987 //ignore sets that do not concern the current layout (vetrtical or horizontal)
1988 if (this->IsVertical()) { //col=1 left, center, right
1989 if (myAlign & gdlwALIGN_CENTER) return wxALIGN_CENTER_HORIZONTAL;
1990 if (myAlign & gdlwALIGN_LEFT) return wxALIGN_LEFT;
1991 if (myAlign & gdlwALIGN_RIGHT) return wxALIGN_RIGHT;
1992 if (myAlign & gdlwALIGN_TOP) return wxALIGN_LEFT;
1993 if (myAlign & gdlwALIGN_BOTTOM) return wxALIGN_RIGHT;
1994 } else if (this->IsHorizontal()) { //row=1
1995 if (myAlign & gdlwALIGN_CENTER) return wxALIGN_CENTER_VERTICAL;
1996 if (myAlign & gdlwALIGN_TOP) return wxALIGN_TOP;
1997 if (myAlign & gdlwALIGN_BOTTOM) return wxALIGN_BOTTOM;
1998 if (myAlign & gdlwALIGN_LEFT) return wxALIGN_TOP;
1999 if (myAlign & gdlwALIGN_RIGHT) return wxALIGN_BOTTOM;
2000 }
2001 return 0;
2002 }
2003
~GDLWidgetTopBase()2004 GDLWidgetTopBase::~GDLWidgetTopBase() {
2005 #ifdef GDL_DEBUG_WIDGETS
2006 std::cout << "~GDLWidgetTopBase(" << widgetID << ")" << std::endl;
2007 #endif
2008 topFrame->NullGDLOwner();
2009
2010 //IMPORTANT: unxregister TLB if was managed
2011 if (this->GetManaged()) CallEventPro("UNXREGISTER", new DLongGDL(widgetID)); //UNXREGISTER defined in XMANAGER.PRO
2012
2013 //send RIP
2014 // create GDL event struct
2015 DStructGDL* ev = new DStructGDL("*TOPLEVEL_DESTROYED*");
2016 ev->InitTag("ID", DLongGDL(widgetID));
2017 ev->InitTag("TOP", DLongGDL(widgetID));
2018 ev->InitTag("HANDLER", DLongGDL(0));
2019 if (this->GetXmanagerActiveCommand() || !this->GetManaged()) {
2020 readlineEventQueue.PushFront(ev); // push front (will be handled next)
2021 } else {
2022 eventQueue.PushFront(ev); // push front (will be handled next)
2023 }
2024 }
2025 /*********************************************************/
2026 // Context Menu pseudo-base
2027 /*********************************************************/
GDLWidgetContextBase(WidgetIDT parentID,EnvT * e,ULong eventFlags_,bool mapWid,DLong col,DLong row,int exclusiveMode_,const DString & resource_name,const DString & rname_mbar,const DString & title_,const DString & display_name,int xpad_,int ypad_,DLong x_scroll_size,DLong y_scroll_size,bool grid_layout,long children_alignment,int space_)2028 GDLWidgetContextBase::GDLWidgetContextBase( WidgetIDT parentID, EnvT* e, ULong eventFlags_,
2029 bool mapWid,
2030 DLong col, DLong row,
2031 int exclusiveMode_,
2032 const DString& resource_name, const DString& rname_mbar,
2033 const DString& title_,
2034 const DString& display_name,
2035 int xpad_, int ypad_,
2036 DLong x_scroll_size, DLong y_scroll_size, bool grid_layout, long children_alignment, int space_)
2037 : GDLWidgetMenu(parentID, e, new DStringGDL(title_), eventFlags_, NULL)
2038 {
2039 GDLWidget* gdlParent = GetWidget( parentID );
2040 assert( gdlParent != NULL);
2041 gdlParent->AddToFollowers(widgetID); //very important, the transient must be deleted if the associated widget is deleted!
2042 wxWindow* parentWindow=dynamic_cast<wxWindow*>(gdlParent->GetWxWidget());
2043 assert( parentWindow != NULL);
2044 //get default value: a menu. May be NULL here
2045 wxMenu *menu = new wxMenu();
2046 theWxContainer = menu; //is not a window
2047 theWxWidget = menu;
2048 buttonType = MENU;
2049
2050 // UPDATE_WINDOW; REALIZE_IF_NEEDED; //no use (TBC)
2051 }
2052
~GDLWidgetContextBase()2053 GDLWidgetContextBase::~GDLWidgetContextBase() {
2054 #ifdef GDL_DEBUG_WIDGETS
2055 std::cout << "~GDLWidgetContextBase(" << widgetID << ")" << std::endl;
2056 #endif
2057 }
2058 /*********************************************************/
2059 // Normal WIDGET_BASE but Tab hosted
2060 /*********************************************************/
GDLWidgetTabbedBase(WidgetIDT parentID,EnvT * e,ULong eventFlags_,bool mapWid,DLong col,DLong row,int exclusiveMode_,const DString & resource_name,const DString & rname_mbar,const DString & title_,const DString & display_name,int xpad_,int ypad_,DLong x_scroll_size,DLong y_scroll_size,bool grid_layout,long children_alignment,int space_)2061 GDLWidgetTabbedBase::GDLWidgetTabbedBase(WidgetIDT parentID, EnvT* e, ULong eventFlags_,
2062 bool mapWid,
2063 DLong col, DLong row,
2064 int exclusiveMode_,
2065 const DString& resource_name, const DString& rname_mbar,
2066 const DString& title_,
2067 const DString& display_name,
2068 int xpad_, int ypad_,
2069 DLong x_scroll_size, DLong y_scroll_size, bool grid_layout, long children_alignment, int space_)
2070 : GDLWidgetBase(parentID, e, eventFlags_, mapWid, col, row, exclusiveMode_, resource_name, rname_mbar, title_, display_name, xpad_, ypad_, x_scroll_size, y_scroll_size, grid_layout, children_alignment, space_)
2071 , myPage(-1)
2072 {
2073 //for historical logic reasons, there must be a container panel child of the tab, that will contain the actual widget, a panel.
2074 //the container is a scrolledwindow OR just a panel.
2075 //it would have been simpler to use just a wxScrolled<> for each container, and have it scroll or not depending on GDLWidget::scrolled.
2076 //this would accessorily eliminate the use of 'scrollSizer' and 'scrollPanel'.
2077 //but this has consequences in all the creation/deletion chain, to be done in time.
2078 GDLWidgetTab* parent = static_cast<GDLWidgetTab*> (GetWidget(parentID));
2079 assert(parent != NULL);
2080
2081 wxNotebook* parentTab = dynamic_cast<wxNotebook*> (parent->GetWxWidget());
2082 assert(parentTab != NULL);
2083
2084 wxString titleWxString = wxString(title_.c_str(), wxConvUTF8);
2085 wxSizer* sz=new wxBoxSizer(wxVERTICAL);
2086 // wxPanel* p=new wxPanel(parentTab, wxID_ANY, wxDefaultPosition, wxDefaultSize);
2087 // p->SetSize(wScrollSize);
2088 if (nrows < 1 && ncols < 1 && frameWidth < 1) frameWidth=1; //set framewidth (temporary) in this case to get good result
2089 CreateBase(parentTab);
2090 // sz->Add(w,DONOTALLOWSTRETCH, wxALL | wxEXPAND, 0);
2091 // p->SetSizer(sz);
2092 // theWxContainer=p;
2093 //
2094 // theWxWidget = p;
2095 wxWindow* w=static_cast<wxWindow*>(theWxContainer); //defined in CreateBase.
2096 myPage=parentTab->GetPageCount();
2097 // parentTab->AddPage(w, titleWxString);
2098 parentTab->InsertPage(myPage, w, titleWxString);
2099 // myPage=parentTab->FindPage(w);
2100
2101 // UPDATE_WINDOW
2102 REALIZE_IF_NEEDED
2103 }
2104 /*********************************************************/
2105 // Normal WIDGET_BASE
2106
2107 /*********************************************************/
GDLWidgetNormalBase(WidgetIDT parentID,EnvT * e,ULong eventFlags_,bool mapWid,DLong col,DLong row,int exclusiveMode_,const DString & resource_name,const DString & rname_mbar,const DString & title_,const DString & display_name,int xpad_,int ypad_,DLong x_scroll_size,DLong y_scroll_size,bool grid_layout,long children_alignment,int space_)2108 GDLWidgetNormalBase::GDLWidgetNormalBase(WidgetIDT parentID, EnvT* e, ULong eventFlags_,
2109 bool mapWid,
2110 DLong col, DLong row,
2111 int exclusiveMode_,
2112 const DString& resource_name, const DString& rname_mbar,
2113 const DString& title_,
2114 const DString& display_name,
2115 int xpad_, int ypad_,
2116 DLong x_scroll_size, DLong y_scroll_size, bool grid_layout, long children_alignment, int space_)
2117 : GDLWidgetBase(parentID, e, eventFlags_, mapWid, col, row, exclusiveMode_, resource_name, rname_mbar, title_, display_name, xpad_, ypad_, x_scroll_size, y_scroll_size, grid_layout, children_alignment, space_) {
2118 // If parent base widget exists ....
2119 GDLWidget* gdlParent = GetWidget(parentID);
2120 assert(gdlParent != NULL);
2121 wxWindow* wxParent = dynamic_cast<wxWindow*> (GetParentPanel());
2122 assert(wxParent != NULL);
2123 CreateBase(wxParent);
2124
2125 // UPDATE_WINDOW
2126 REALIZE_IF_NEEDED
2127 }
2128
GetGeometry(wxRealPoint fact)2129 DStructGDL* GDLWidgetBase::GetGeometry(wxRealPoint fact) {
2130 if (!this->IsRealized()) this->Realize(true, false); //necessary if a geometry request is done previous to the command widget_control,xxx,,/Realize !
2131 int panel_xoff = 0;
2132 int panel_yoff = 0;
2133
2134 int ixsize = 0, iysize = 0, iscr_xsize = 0, iscr_ysize = 0;
2135 DFloat xsize = 0;
2136 DFloat ysize = 0;
2137 DFloat scr_xsize = 0;
2138 DFloat scr_ysize = 0;
2139 DFloat xoffset = 0;
2140 DFloat yoffset = 0;
2141 DFloat margin = 0;
2142 //reported size includes xpad and ypad.
2143 int ixpad=this->getXPad();
2144 int iypad=this->getYPad();
2145 DStructGDL* ex = new DStructGDL("WIDGET_GEOMETRY");
2146
2147 wxWindow* w = dynamic_cast<wxWindow*> (theWxContainer);
2148 if (w == NULL) return ex;
2149 if (frameWidth > 0 && (ixpad>0 || iypad >0)) w=w->GetChildren()[0]; //padxpady is the first child of frame
2150 wxRect z = w->GetRect();
2151
2152 margin=frameWidth;
2153 GDLWidgetBase* container = static_cast<GDLWidgetBase*> (this->GetMyParent());
2154 if (container == NULL) { //TLB
2155 // w->GetScreenPosition(&panel_xoff, &panel_yoff);
2156 xoffset = panel_xoff+margin;
2157 yoffset = panel_yoff+margin;
2158 } else {
2159 xoffset = z.x+margin;
2160 yoffset = z.y+margin;
2161 }
2162 iscr_xsize = z.width-2*margin;
2163 iscr_ysize = z.height-2*margin;
2164 wxSize s = w->GetClientSize();
2165 ixsize = s.x-2*margin;
2166 iysize = s.y-2*margin;
2167 //size is in pixels, pass in requested units (1.0 default)
2168 xsize = ixsize / fact.x;
2169 ysize = iysize / fact.y;
2170 scr_xsize = iscr_xsize / fact.x;
2171 scr_ysize = iscr_ysize / fact.y;
2172 xoffset /= fact.x;
2173 yoffset /= fact.y;
2174 margin /= fact.x;
2175
2176 ex->InitTag("XOFFSET", DFloatGDL(xoffset));
2177 ex->InitTag("YOFFSET", DFloatGDL(yoffset));
2178 ex->InitTag("XSIZE", DFloatGDL(xsize));
2179 ex->InitTag("YSIZE", DFloatGDL(ysize));
2180 ex->InitTag("SCR_XSIZE", DFloatGDL(scr_xsize));
2181 ex->InitTag("SCR_YSIZE", DFloatGDL(scr_ysize));
2182 ex->InitTag("MARGIN", DFloatGDL(margin));
2183
2184 //reported size includes xpad and ypad.
2185 DFloat xpad=ixpad/ fact.x;
2186 DFloat ypad=iypad/ fact.y;
2187 DFloat space=this->getSpace()/ fact.x;
2188 ex->InitTag( "XPAD", DFloatGDL( xpad ) );
2189 ex->InitTag( "YPAD", DFloatGDL( ypad ) );
2190 ex->InitTag( "SPACE", DFloatGDL( space) );
2191 return ex;
2192 }
2193
2194 //DStructGDL* GDLWidgetBase::GetGeometry(wxRealPoint fact)
2195 //{
2196 // if (!this->IsRealized()) this->Realize(true,false);//necessary if a geometry request is done previous to the command widget_control,xxx,,/Realize !
2197 // //the only way to get accurate positions seems to get the screen position of the Panel
2198 // //in which the window is (the Panel is the useful part of the Base) and substract them from the
2199 // //screen position of the siwget itself. And get the margin (=frame) size if any.
2200 // //for Bases, one has also to retrieve xpad,ypad and space;
2201 // int panel_xoff = 0;
2202 // int panel_yoff = 0;
2203 //
2204 // GDLWidgetBase* container = static_cast<GDLWidgetBase*> (this->GetMyParent());
2205 // if (container != NULL) { //not TLB
2206 // wxPanel* p = dynamic_cast<wxPanel*> (container->GetPanel());
2207 // p->GetScreenPosition(&panel_xoff, &panel_yoff);
2208 // }
2209 // int ixsize = 0, iysize = 0, iscr_xsize = 0, iscr_ysize = 0;
2210 // int widget_xoff = 0;
2211 // int widget_yoff = 0;
2212 // DFloat xsize = 0;
2213 // DFloat ysize = 0;
2214 // DFloat scr_xsize = 0;
2215 // DFloat scr_ysize = 0;
2216 // DFloat xoffset = 0;
2217 // DFloat yoffset = 0;
2218 // DFloat margin = frameWidth;
2219 //
2220 // wxWindow* test = dynamic_cast<wxWindow*> (theWxWidget);
2221 //
2222 // if (test != NULL) {
2223 // //offsets. easy.
2224 // test->GetScreenPosition(&widget_xoff, &widget_yoff);
2225 // xoffset = widget_xoff - panel_xoff;
2226 // yoffset = widget_yoff - panel_yoff;
2227 //
2228 // test->GetSize(&iscr_xsize, &iscr_ysize); //contains frame size if framed
2229 //
2230 // ixsize = iscr_xsize; //with scrollbars, if any, and frames
2231 // iysize = iscr_ysize;
2232 //
2233 // //reported size includes xpad and ypad.
2234 // DFloat xpad=this->getXPad()/ fact.x;
2235 // DFloat ypad=this->getYPad()/ fact.y;
2236 // DFloat space=this->getSpace()/ fact.x;
2237 // //offset is including xpad,ypad
2238 // xoffset -= xpad;
2239 // yoffset -= ypad;
2240 // //size is in pixels, pass in requested units (1.0 default)
2241 // xsize = ixsize / fact.x + 2*margin;
2242 // ysize = iysize / fact.y + 2*margin;
2243 // scr_xsize = iscr_xsize / fact.x;
2244 // scr_ysize = iscr_ysize / fact.y;
2245 // xoffset /= fact.x;
2246 // yoffset /= fact.y;
2247 // margin /= fact.x;
2248 // }
2249 //
2250 // DStructGDL* ex = new DStructGDL("WIDGET_GEOMETRY");
2251 // ex->InitTag("XOFFSET", DFloatGDL(xoffset));
2252 // ex->InitTag("YOFFSET", DFloatGDL(yoffset));
2253 // ex->InitTag("XSIZE", DFloatGDL(xsize));
2254 // ex->InitTag("YSIZE", DFloatGDL(ysize));
2255 // ex->InitTag("SCR_XSIZE", DFloatGDL(scr_xsize));
2256 // ex->InitTag("SCR_YSIZE", DFloatGDL(scr_ysize));
2257 // ex->InitTag("MARGIN", DFloatGDL(margin));
2258 // ex->InitTag( "XPAD", DFloatGDL( xpad ) );
2259 // ex->InitTag( "YPAD", DFloatGDL( ypad ) );
2260 // ex->InitTag( "SPACE", DFloatGDL( space) );
2261 // return ex;
2262 //}
2263
2264 //// called from event handling thread
2265 //// sends a destroy event for itself
2266 //void GDLWidgetTopBase::SelfDestroy()
2267 //{
2268 // assert( parentID == NullID );
2269 // // create GDL event struct
2270 // DStructGDL* ev = new DStructGDL( "*WIDGET_DESTROY*" );
2271 // ev->InitTag( "ID", DLongGDL( widgetID ) );
2272 // ev->InitTag( "TOP", DLongGDL( widgetID ) );
2273 // ev->InitTag( "HANDLER", DLongGDL( 0 ) );
2274 // if ( this->GetXmanagerActiveCommand( ) || !this->GetManaged() ){
2275 // readlineEventQueue.PushFront( ev ); // push front (will be handled next)
2276 // } else {
2277 // eventQueue.PushFront( ev ); // push front (will be handled next)
2278 // }
2279 //}
2280
mapBase(bool val)2281 void GDLWidgetBase::mapBase(bool val){
2282 wxWindow* me=dynamic_cast<wxWindow*>(theWxContainer);
2283 if (me) me->Show(val); else {cerr<<"Warning: GDLWidgetBase::mapBase(): Non-existent widget!\n"; return;}
2284 }
mapBase(bool val)2285 void GDLWidgetTopBase::mapBase(bool val){
2286 topFrame->Show(val);
2287 }
mapBase(bool val)2288 void GDLWidgetTabbedBase::mapBase(bool val){
2289 //Note: it is impossible to reproduce the IDL behaviour (tab is present but void) with wxWidgets unless doing ridiculously complicated things.
2290 wxWindow* me=dynamic_cast<wxWindow*>(theWxContainer);
2291 if (me) me->Show(val); else {cerr<<"Warning: GDLWidgetTabbedBase::mapBase(): Non-existent widget!\n"; return;}
2292 }
2293 // Order in which widgets are plotted is different btw wxWindow and IDL if one does not do the following tricks:
DoReorderColWidgets(int code,int style,int border)2294 void GDLWidgetBase::DoReorderColWidgets(int code,int style, int border) {
2295 int nchild = this->NChildren();
2296 //get children list...
2297 DLongGDL* gdlwList= GetChildrenList();
2298 // set up window list, get existing code, style and border for each of the children
2299 std::vector<int> proportionlist;
2300 std::vector<wxWindow*> windowlist;
2301 std::vector<int> flaglist;
2302 std::vector<int> borderlist;
2303 for (int i = 0; i < nchild; ++i) {
2304 GDLWidget* g=GetWidget((*gdlwList)[i]);
2305 wxWindow* w=static_cast<wxWindow*>(g->GetWxContainer());
2306 windowlist.push_back(w);
2307 wxSizerItem* s=widgetSizer->GetItem(w);
2308 if (s==NULL) { //this is a new window that has not yet been added (the widget is Realized) : use passed values
2309 proportionlist.push_back(code);
2310 flaglist.push_back(style);
2311 borderlist.push_back(border);
2312 } else { //use existing values
2313 proportionlist.push_back(s->GetProportion());
2314 flaglist.push_back(s->GetFlag());
2315 borderlist.push_back(s->GetBorder());
2316 }
2317 }
2318 GDLDelete(gdlwList);
2319
2320 //compute new positions (align items along column 1, then 2 etc... when wxWidget will insert them col1,col2,col1,col2, etc..)
2321 int local_nchild=nchild;
2322 // method for COL=n , row is growing
2323 //This should be called only for /COL => nrows is 0
2324 int local_ncols = ncols;
2325 int local_nrows = local_nchild / local_ncols;
2326 if (local_nrows * local_ncols < local_nchild) local_nrows++;
2327 //how many filled cols?
2328 int reste = (local_ncols * local_nrows) - local_nchild;
2329 int filledcols = local_ncols - reste;
2330
2331 //we create the corresponding flexigridsizer, destroy the previous one, assign back to widgetSizer
2332 wxFlexGridSizer* newWidgetSizer = new wxFlexGridSizer(local_nrows, local_ncols, border, border);
2333 widgetPanel->SetSizer(newWidgetSizer, true);
2334 widgetPanel->SetAutoLayout(true);
2335 if (grid) {
2336 newWidgetSizer->SetFlexibleDirection(wxHORIZONTAL);
2337 newWidgetSizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL);
2338 }
2339 widgetSizer = newWidgetSizer;
2340
2341 //so the first 'filledcols' will be filled, the rest will have (apparently) one row less.
2342 //we have to insert a place holder in the list of childrens at each index corresponding to the last row, starting at the first incomplete column.
2343 //widgets indexes are k=icol*local_nrows+jrow, compute a new indexlist where empty indexes are those jumped
2344
2345
2346 int list[local_ncols * local_nrows];
2347 int i = 0;
2348 int k = 0;
2349 int avoidrow = (reste == 0) ? local_nrows : local_nrows - 1;
2350 int lastfilledcol = (reste == 0) ? local_ncols : filledcols - 1;
2351 // list of indexes as displayed in colums (idl) with -1 when there should be a void.
2352 for (int icol = 0; icol < local_ncols; icol++) {
2353 for (int jrow = 0; jrow < local_nrows; jrow++) {
2354 if ((icol > lastfilledcol) && (jrow == avoidrow)) {
2355 list[k++] = -1;
2356 } else {
2357 list[k++] = i++;
2358 }
2359 }
2360 }
2361
2362 //find transposed values: read list in transposed order, use a local_nrows stride.
2363 int stride = local_nrows;
2364 int outer_stride = local_ncols*local_nrows;
2365 for (k = 0, i = 0; i < nchild; ++i) {
2366 widgetSizer->Add(windowlist[list[k]], proportionlist[list[k]],flaglist[list[k]],borderlist[list[k]]);
2367 k += stride;
2368 if (k >= outer_stride) {
2369 k -= outer_stride;
2370 k++;
2371 }
2372 }
2373 }
2374
ReorderWidgets()2375 void GDLWidgetBase::ReorderWidgets()
2376 {
2377 // NULL widget Sizer means 1) no row no col was asked for (so, no sizer) or, if col>1, we have to create the sizer here and add children in specific order.
2378 // do *not* forget to give back the sizer pointer instead of the previous NULL to the base widget!
2379 if (widgetSizer == NULL) return;
2380 if (ncols > 1) DoReorderColWidgets(0,0,space); //need to reorder widget for /COL only
2381 }
2382
ReorderForANewWidget(wxWindow * w,int code,int style,int border)2383 void GDLWidgetBase::ReorderForANewWidget(wxWindow* w, int code,int style, int border)
2384 {
2385 if (widgetSizer == NULL) return;
2386 if (ncols > 1 ) DoReorderColWidgets(code, style, border); //need to reorder widget for /COL only
2387 else widgetSizer->Add(w, code, style, border ); // just add widget in sizer for /ROW
2388 }
2389 /*********************************************************/
2390 // for WIDGET_TAB
2391 /*********************************************************/
GDLWidgetTab(WidgetIDT p,EnvT * e,ULong eventFlags_,DLong location,DLong multiline)2392 GDLWidgetTab::GDLWidgetTab( WidgetIDT p, EnvT* e, ULong eventFlags_, DLong location, DLong multiline )
2393 : GDLWidgetContainer( p, e, eventFlags_ ) {
2394
2395 scrolled=false; //TAB has no Scrolled.
2396
2397 // GDLWidget* gdlParent = GetWidget( parentID );
2398 // widgetPanel = GetParentPanel( );
2399
2400 wxSizer* parentSizer = GetParentSizer( );
2401
2402 long style = wxNB_TOP;
2403 if ( location == 1 ) style = wxNB_BOTTOM;
2404 if ( location == 2 ) style = wxNB_LEFT;
2405 if ( location == 3 ) style = wxNB_RIGHT;
2406
2407 if ( multiline != 0 )
2408 style |= wxNB_MULTILINE; //works only for WINDOWS.
2409
2410 wxPanel* panel_if_framed;
2411 wxPanel* container=widgetPanel; //default container if no intervening panels
2412 wxSizer* framesizer=NULL;
2413 wxNotebook * notebook;
2414 if (frameWidth>0) { //frame
2415 panel_if_framed=new wxPanel(container, wxID_ANY, wOffset, wxDefaultSize, gdlBORDER_EXT);
2416 theWxContainer = panel_if_framed;
2417 framesizer=new wxBoxSizer(wxVERTICAL);
2418 panel_if_framed->SetSizer(framesizer);
2419 container=panel_if_framed; //becomes container for further widgets
2420 if (parentSizer) parentSizer->Add(container, DONOTALLOWSTRETCH, widgetAlignment(),gdlFRAME_MARGIN); //add to parent sizer
2421 notebook = new wxNotebook( container, widgetID, wxDefaultPosition, computeWidgetSize( ), style );
2422 theWxWidget = notebook;
2423 framesizer->Add(notebook,DONOTALLOWSTRETCH,wxALL,frameWidth);
2424 } else {
2425 notebook = new wxNotebook( container, widgetID, wOffset, computeWidgetSize( ), style );
2426 theWxContainer = theWxWidget = notebook;
2427 if (parentSizer) parentSizer->Add(notebook,DONOTALLOWSTRETCH,widgetAlignment()|wxALL, gdlSPACE);
2428 }
2429 //wxNotebook DOES NOT USE a sizer.
2430 this->AddToDesiredEvents(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,wxNotebookEventHandler(gdlwxFrame::OnPageChanged),notebook);
2431 }
~GDLWidgetTab()2432 GDLWidgetTab::~GDLWidgetTab() {
2433 #ifdef GDL_DEBUG_WIDGETS
2434 std::cout << "~GDLWidgetTab(" << widgetID << ")" << std::endl;
2435 #endif
2436 }
2437
GetTabNumber()2438 BaseGDL* GDLWidgetTab::GetTabNumber(){
2439 wxNotebook * notebook=dynamic_cast<wxNotebook*>(theWxWidget);
2440 assert( notebook != NULL);
2441 return new DIntGDL(notebook->GetPageCount());
2442 }
2443
GetTabCurrent()2444 BaseGDL* GDLWidgetTab::GetTabCurrent(){
2445 wxNotebook * notebook=dynamic_cast<wxNotebook*>(theWxWidget);
2446 assert( notebook != NULL);
2447 return new DIntGDL(notebook->GetSelection());
2448 }
2449
SetTabCurrent(int val)2450 void GDLWidgetTab::SetTabCurrent(int val){
2451 wxNotebook * notebook=dynamic_cast<wxNotebook*>(theWxWidget);
2452 assert( notebook != NULL);
2453 if (val<notebook->GetPageCount()){
2454 // notebook->GetPage(val)->Raise();
2455 notebook->ChangeSelection(val);
2456 }
2457 }
2458
GetTabMultiline()2459 BaseGDL* GDLWidgetTab::GetTabMultiline(){
2460 wxNotebook * notebook=dynamic_cast<wxNotebook*>(theWxWidget);
2461 assert( notebook != NULL);
2462 return new DIntGDL(notebook->GetExtraStyle()&wxNB_MULTILINE);
2463 }
2464
2465
2466 /*********************************************************/
2467 // for WIDGET_TABLE
2468 /*********************************************************/
2469 //overrides method to label the columns & lines
GetRowLabelValue(int row)2470 wxString wxGridTableBase::GetRowLabelValue( int row )
2471 {
2472 wxString s;
2473
2474 // RD: Starting the rows at zero confuses users,
2475 // no matter how much it makes sense to us geeks.
2476 // GD: So IDL and GDL are for geeks.
2477 s << row ;
2478
2479 return s;
2480 }
GetColLabelValue(int col)2481 wxString wxGridTableBase::GetColLabelValue( int col )
2482 {
2483 wxString s;
2484 s << col ;
2485
2486 return s;
2487 }
2488
GDLWidgetTable(WidgetIDT p,EnvT * e,DByteGDL * alignment_,DStringGDL * amPm_,DByteGDL * backgroundColor_,DByteGDL * foregroundColor_,DStringGDL * columnLabels_,int majority_,DLongGDL * columnWidth_,DStringGDL * daysOfWeek_,bool disjointSelection_,DByteGDL * editable_,DStringGDL * format_,DStringGDL * month_,bool noColumnHeaders_,bool noRowHeaders_,bool resizeableColumns_,bool resizeableRows_,DLongGDL * rowHeights_,DStringGDL * rowLabels_,BaseGDL * value_,DLong xScrollSize_,DLong yScrollSize_,DStringGDL * valueAsStrings_,DULong eventFlags_)2489 GDLWidgetTable::GDLWidgetTable( WidgetIDT p, EnvT* e,
2490 DByteGDL* alignment_,
2491 DStringGDL* amPm_,
2492 DByteGDL* backgroundColor_,
2493 DByteGDL* foregroundColor_,
2494 DStringGDL* columnLabels_,
2495 int majority_,
2496 DLongGDL* columnWidth_,
2497 DStringGDL* daysOfWeek_,
2498 bool disjointSelection_,
2499 DByteGDL* editable_,
2500 DStringGDL* format_,
2501 //bool ignoreAccelerators_,
2502 DStringGDL* month_,
2503 bool noColumnHeaders_,
2504 bool noRowHeaders_,
2505 bool resizeableColumns_,
2506 bool resizeableRows_,
2507 DLongGDL* rowHeights_,
2508 DStringGDL* rowLabels_,
2509 //DLong tabMode_,
2510 BaseGDL* value_,
2511 DLong xScrollSize_,
2512 DLong yScrollSize_,
2513 DStringGDL* valueAsStrings_,
2514 DULong eventFlags_
2515 )
2516 : GDLWidget( p, e, value_, eventFlags_ )
2517 , table_alignment( alignment_ )
2518 , amPm( amPm_ )
2519 , backgroundColor( backgroundColor_ )
2520 , foregroundColor( foregroundColor_ )
2521 , columnLabels( columnLabels_ )
2522 , majority ( majority_ )
2523 , columnWidth( columnWidth_ )
2524 , daysOfWeek( daysOfWeek_ )
2525 , disjointSelection( disjointSelection_ )
2526 , editable( editable_)
2527 , format( format_ )
2528 //, ignoreAccelerators( ignoreAccelerators_ )
2529 , month( month_ )
2530 , noColumnHeaders( noColumnHeaders_ )
2531 , noRowHeaders( noRowHeaders_ )
2532 , resizeableColumns( resizeableColumns_ )
2533 , resizeableRows( resizeableRows_ )
2534 , rowHeights( rowHeights_ )
2535 , rowLabels( rowLabels_ )
2536 //, tabMode( tabMode_ )
2537 , x_scroll_size( xScrollSize_ )
2538 , y_scroll_size( yScrollSize_)
2539 , valueAsStrings( valueAsStrings_ )
2540 , updating(false)
2541 {
2542 GDLWidget* gdlParent = GetWidget( parentID );
2543 widgetPanel = GetParentPanel( );
2544 widgetSizer = GetParentSizer( );
2545
2546 //due to subtle problems in the absence of a frame around, a 0 or negative frame becomes a frame=1
2547 // if (frameWidth <1) frameWidth=1;
2548
2549 START_ADD_EVENTUAL_FRAME
2550
2551 widgetStyle=widgetAlignment();
2552
2553 //at this stage, valueAsStrings is OK dim 1 or 2 BUT vVALUE MAY BE NULL!
2554 SizeT numRows,numCols;
2555 if (valueAsStrings->Rank()==1) {
2556 numRows=1;
2557 numCols=valueAsStrings->Dim(0); //lines
2558 } else {
2559 numRows=valueAsStrings->Dim(1);
2560 numCols=valueAsStrings->Dim(0);
2561 }
2562 SizeT grid_nrows=(wSize.y<=0)?numRows:wSize.y;
2563 SizeT grid_ncols=(wSize.x<=0)?numCols:wSize.x;
2564
2565 wxGridGDL *grid = new wxGridGDL( widgetPanel, widgetID, wxDefaultPosition, wxDefaultSize);
2566 //important:set wxWidget here. (fonts)
2567 theWxContainer = theWxWidget = grid;
2568 // important: use adapted font for further sizes & shapes. Define font for labels AND cells.
2569 this->setFont();
2570 //Column Width Before creating
2571 bool hasColumnWidth=(columnWidth!=NULL);
2572 if (hasColumnWidth) { //one value set for all?
2573 if (columnWidth->N_Elements()==1) {
2574 grid->SetDefaultColSize((*columnWidth)[0]*unitConversionFactor.x) ;
2575 hasColumnWidth=false;
2576 }
2577 }
2578 //RowHeight
2579 bool hasRowHeights=(rowHeights!=NULL);
2580 if (hasRowHeights) { //one value set for all?
2581 if (rowHeights->N_Elements()==1) {
2582 grid->SetDefaultRowSize((*rowHeights)[0]*unitConversionFactor.y) ;
2583 hasRowHeights=false;
2584 }
2585 }
2586 //Alignment
2587 bool hasAlignment=(table_alignment!=NULL);
2588 if (hasAlignment) {
2589 if (table_alignment->N_Elements()==1) { //singleton case
2590 switch( (*table_alignment)[0] ){
2591 case 0:
2592 grid->SetDefaultCellAlignment(wxALIGN_LEFT,wxALIGN_CENTRE); break;
2593 case 1:
2594 grid->SetDefaultCellAlignment(wxALIGN_CENTRE,wxALIGN_CENTRE); break;
2595 case 2:
2596 grid->SetDefaultCellAlignment(wxALIGN_RIGHT,wxALIGN_CENTRE);
2597 }
2598 hasAlignment=false; //otherwise will be treated cell by cell below!
2599 }
2600 }
2601 //General Editability
2602 bool isEditable=(editable!=NULL);
2603 if (isEditable) {
2604 if (editable->N_Elements()==1) { //singleton case
2605 if ((*editable)[0]==0) isEditable=false;
2606 else {grid->EnableEditing(true); isEditable=false;}
2607 }
2608 } else grid->EnableEditing(false);
2609 if (isEditable) grid->EnableEditing(true); //since now isEditable means "individually editable", which needs global editing set.
2610 //Single Background Colour
2611 bool isBackgroundColored=(backgroundColor!=NULL);
2612 if (isBackgroundColored) { //one value set for all?
2613 if (backgroundColor->N_Elements()==3) {
2614 grid->SetDefaultCellBackgroundColour(wxColour((*backgroundColor)[0],(*backgroundColor)[1],(*backgroundColor)[2])) ;
2615 isBackgroundColored=false;
2616 }
2617 }
2618 //Single Text Colour
2619 bool isForegroundColored=(foregroundColor!=NULL);
2620 if (isForegroundColored) { //one value set for all?
2621 if (foregroundColor->N_Elements()==3) {
2622 grid->SetDefaultCellTextColour(wxColour((*foregroundColor)[0],(*foregroundColor)[1],(*foregroundColor)[2])) ;
2623 isForegroundColored=false;
2624 }
2625 }
2626 //No column Headers
2627 if (noColumnHeaders) grid->SetColLabelSize(0);
2628 //No row Headers
2629 if (noRowHeaders) grid->SetRowLabelSize(0);
2630 //end General Setup
2631 int selmode = wxGrid::wxGridSelectCells; //wxWidgets's modes do not reflect IDL's. We trick the selections according to modes in eventhandler.
2632 if (!resizeableColumns) grid->DisableDragColSize();
2633 if (!resizeableRows) grid->DisableDragRowSize();
2634 grid->CreateGrid( grid_nrows, grid_ncols, static_cast<wxGrid::wxGridSelectionModes>(selmode));
2635 // Set grid cell contents as strings. Note that there may be less or more cells than valueAsStrings, due to possibly different wSize.x,wSize.y :
2636
2637 for ( int ival=0, i=0; i<grid_nrows; ++i, ++ival) for (int jval=0, j=0; j<grid_ncols; ++j, ++jval)
2638 {
2639 if (ival < numRows && jval < numCols ) {
2640 StrTrim((*valueAsStrings)[jval*numRows+ival]);
2641 grid->SetCellValue( i, j ,wxString(((*valueAsStrings)[jval*numRows+ival]).c_str(), wxConvUTF8 ) );
2642 }
2643 }
2644
2645 //Editability
2646 //take too long as soon as table has a more than a few elements. Fixme!
2647 //if (isEditable) {SizeT k=0; for (SizeT irow=0; irow< grid_nrows; ++irow) for (SizeT icol=0; icol< grid_ncols; ++icol) {grid->SetReadOnly( irow, icol, ((*editable)[k%editable->N_Elements()]==0));++k;}}
2648 //colors per element
2649 if (isBackgroundColored) this->DoBackgroundColor();
2650 if (isForegroundColored) this->DoForegroundColor();
2651 if (hasColumnWidth) this->DoColumnWidth();
2652 if (hasRowHeights) this->DoRowHeights();
2653 //treat other alignment cases.
2654 if (hasAlignment) this->DoAlign();
2655
2656 if (columnLabels!=NULL)this->DoColumnLabels();
2657 if (rowLabels!=NULL) this->DoRowLabels();
2658
2659 //get back on sizes. Do we enforce some size or scroll_size, in columns/rows:
2660 int currentColLabelHeight = grid->GetColLabelSize();
2661 int currentRowLabelWidth = grid->GetRowLabelSize();
2662
2663 int fullsizex=currentRowLabelWidth;
2664 int fullsizey=currentColLabelHeight;
2665 for (SizeT i=0; i< numCols ; ++i) fullsizex+=(i<grid_ncols)?grid->GetColSize(i):grid->GetDefaultColSize();
2666 for (SizeT j=0; j< numRows ; ++j) fullsizey+=(j<grid_nrows)?grid->GetRowHeight(j):grid->GetDefaultRowSize();
2667
2668 int visiblesizex=currentRowLabelWidth;
2669 int visiblesizey=currentColLabelHeight;
2670 for (SizeT i=0; i< grid_ncols ; ++i) visiblesizex+=grid->GetColSize(i);
2671 for (SizeT j=0; j< grid_nrows ; ++j) visiblesizey+=grid->GetRowHeight(j);
2672
2673 int sizex=-1;
2674 int sizey=-1;
2675 int scr_sizex=-1;
2676 int scr_sizey=-1;
2677 if ( wSize.x > 0 ) { sizex = visiblesizex; //size in columns given
2678 } else {sizex=fullsizex;}
2679 if ( wSize.y > 0 ) { sizey = visiblesizey; //size in rows given
2680 } else {sizey=fullsizey;}
2681 if ( x_scroll_size > 0 ) { //scroll size is in columns
2682 scrolled=true;
2683 scr_sizex=currentRowLabelWidth+gdlSCROLL_HEIGHT_X;
2684 for (SizeT i=0; i< x_scroll_size ; ++i) scr_sizex+=grid->GetColSize(i);
2685 scr_sizex=min(scr_sizex,fullsizex);
2686 if (y_scroll_size <=0) y_scroll_size=x_scroll_size;
2687 }
2688 if ( y_scroll_size > 0 ) { //rows
2689 scrolled=true;
2690 scr_sizey=currentColLabelHeight+gdlSCROLL_WIDTH_Y;
2691 for (SizeT j=0; j< y_scroll_size ; ++j) scr_sizey+=grid->GetRowHeight(j);
2692 scr_sizey=min(scr_sizey,fullsizey);
2693 }
2694 //fix size if relevant
2695 if (scrolled && scr_sizex == -1) scr_sizex = (sizex>0)?sizex:fullsizex;
2696 if (scrolled && scr_sizey == -1) scr_sizey = (sizey>0)?sizey:fullsizey;
2697 //wScrXSize etc to be considered since sizes are not in pixels:
2698 if (wScreenSize.x>0) {scr_sizex=wScreenSize.x; scrolled=true;}
2699 if (wScreenSize.y>0) {scr_sizey=wScreenSize.y; scrolled=true;}
2700 //wxGrid IS a scrolled window
2701 if (scrolled) {
2702 grid->ShowScrollbars(wxSHOW_SB_ALWAYS,wxSHOW_SB_ALWAYS);
2703 grid->SetInitialSize(wxSize(scr_sizex, scr_sizey));
2704 } else {
2705 if (wSize.x>0||wSize.y>0) {
2706 grid->SetInitialSize(wxSize(sizex,sizey));
2707 }
2708 }
2709 grid->SetScrollLineX(grid->GetColSize(0));
2710 grid->SetScrollLineY(grid->GetRowHeight(0));
2711
2712 END_ADD_EVENTUAL_FRAME
2713 TIDY_WIDGET(gdlBORDER_SPACE);
2714
2715 this->AddToDesiredEvents( wxEVT_GRID_COL_SIZE,wxGridSizeEventHandler(wxGridGDL::OnTableColResizing),grid);
2716 this->AddToDesiredEvents( wxEVT_GRID_ROW_SIZE,wxGridSizeEventHandler(wxGridGDL::OnTableRowResizing),grid);
2717 this->AddToDesiredEvents( wxEVT_GRID_RANGE_SELECT,wxGridRangeSelectEventHandler(wxGridGDL::OnTableRangeSelection),grid);
2718 this->AddToDesiredEvents( wxEVT_GRID_SELECT_CELL,wxGridEventHandler(wxGridGDL::OnTableCellSelection),grid);
2719 // this->AddToDesiredEvents( wxEVT_GRID_CELL_LEFT_CLICK,wxGridEventHandler(wxGridGDL::OnTableCellSelection),grid);
2720
2721 // UPDATE_WINDOW
2722 REALIZE_IF_NEEDED
2723 }
2724
IsSomethingSelected()2725 bool GDLWidgetTable::IsSomethingSelected(){
2726 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2727 assert( grid != NULL);
2728 return grid->IsSomethingSelected();
2729 }
2730
GetSelection()2731 DLongGDL* GDLWidgetTable::GetSelection( ) {
2732 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2733 assert( grid != NULL);
2734 SizeT k = 0;
2735 DLongGDL * sel;
2736 std::vector<wxPoint> list = grid->GetSelectedDisjointCellsList( );
2737 if ( disjointSelection ) { //pairs lists
2738 if ( list.size( ) < 1 ) {sel = new DLongGDL( 2, BaseGDL::ZERO ); sel->Dec(); return sel;} //returns [-1,-1] if nothing selected
2739 SizeT dims[2];
2740 dims[0] = 2;
2741 dims[1] = list.size( );
2742 dimension dim( dims, 2 );
2743 sel = new DLongGDL( dim );
2744 for ( std::vector<wxPoint>::iterator it = list.begin( ); it != list.end( ); ++it ) {
2745 (*sel)[k++] = (*it).y;
2746 (*sel)[k++] = (*it).x;
2747 }
2748 } else { //4 values
2749 wxGridCellCoordsArray selectionTL = grid->GetSelectionBlockTopLeft( );
2750 wxGridCellCoordsArray selectionBR = grid->GetSelectionBlockBottomRight( );
2751 sel = new DLongGDL( 4, BaseGDL::ZERO ); sel->Dec(); //will return [-1,-1,-1,-1] if nothing selected
2752 if (!selectionTL.IsEmpty() && !selectionBR.IsEmpty()){ //ok with a block...
2753 //LEFT TOP BOTTOM RIGHT
2754 (*sel)[0] = selectionTL[0].GetCol( );
2755 (*sel)[1] = selectionTL[0].GetRow( );
2756 (*sel)[2] = selectionBR[0].GetCol( );
2757 (*sel)[3] = selectionBR[0].GetRow( );
2758 } else {
2759 //try columns, rows, and singletons
2760 wxArrayInt selectionRow=grid->GetSelectedRows();
2761 wxArrayInt selectionCol=grid->GetSelectedCols();
2762 if ( selectionRow.GetCount() >0 ) {
2763 (*sel)[0] = 0;
2764 (*sel)[1] = selectionRow[0];
2765 (*sel)[2] = grid->GetNumberCols()-1;
2766 (*sel)[3] = selectionRow[selectionRow.GetCount()-1];
2767 } else if ( selectionCol.GetCount() >0 ) {
2768 (*sel)[0] = selectionCol[0];
2769 (*sel)[1] = 0;
2770 (*sel)[2] = selectionCol[selectionCol.GetCount()-1];
2771 (*sel)[3] = grid->GetNumberRows()-1;
2772 } else {
2773 wxGridCellCoordsArray cellSelection = grid->GetSelectedCells( );
2774 if (cellSelection.size()>0) {
2775 int row = cellSelection[0].GetRow();
2776 int col = cellSelection[0].GetCol();
2777 (*sel)[0] = col;
2778 (*sel)[1] = row;
2779 (*sel)[2] = col;
2780 (*sel)[3] = row;
2781 }
2782 }
2783 return sel;
2784 }
2785
2786 }
2787 return sel;
2788 }
2789
ClearSelection()2790 void GDLWidgetTable::ClearSelection()
2791 {
2792 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2793 assert( grid != NULL);
2794 updating=true;
2795 grid->ClearSelection();
2796 updating=false;
2797 }
2798
DoAlign()2799 void GDLWidgetTable::DoAlign() {
2800 if (table_alignment->N_Elements( )==0) {return;}
2801 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2802 assert( grid != NULL);
2803 int nRows = grid->GetNumberRows( );
2804 int nCols = grid->GetNumberCols( );
2805 SizeT k = 0;
2806 grid->BeginBatch();
2807 for ( SizeT i = 0; i < nRows; ++i ) {
2808 for ( SizeT j = 0; j < nCols; ++j ) {
2809 switch ( (*table_alignment)[k % table_alignment->N_Elements( )] ) {
2810 case 0:
2811 grid->SetCellAlignment( i, j, wxALIGN_LEFT, wxALIGN_CENTRE );
2812 break;
2813 case 1:
2814 grid->SetCellAlignment( i, j, wxALIGN_CENTRE, wxALIGN_CENTRE );
2815 break;
2816 case 2:
2817 grid->SetCellAlignment( i, j, wxALIGN_RIGHT, wxALIGN_CENTRE );
2818 }
2819 k++;
2820 if ( table_alignment->N_Elements( ) > 1 ) if ( k == table_alignment->N_Elements( ) ) break;
2821 }
2822 if ( table_alignment->N_Elements( ) > 1 ) if ( k == table_alignment->N_Elements( ) ) break;
2823 }
2824 grid->EndBatch();
2825 }
2826
DoAlign(DLongGDL * selection)2827 void GDLWidgetTable::DoAlign(DLongGDL* selection) {
2828 if (table_alignment->N_Elements( )==0) {return;}
2829 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2830 assert( grid != NULL);
2831 SizeT k = 0;
2832 grid->BeginBatch();
2833 if (selection->Rank()==0) { //use current wxWidgets selection
2834 std::vector<wxPoint> list=grid->GetSelectedDisjointCellsList();
2835 for ( std::vector<wxPoint>::iterator it = list.begin(); it !=list.end(); ++it) {
2836 int ali;
2837 switch ( (*table_alignment)[k % table_alignment->N_Elements( )] ) {
2838 case 0:
2839 ali = wxALIGN_LEFT;
2840 break;
2841 case 1:
2842 ali = wxALIGN_CENTRE;
2843 break;
2844 case 2:
2845 ali = wxALIGN_RIGHT;
2846 }
2847 grid->SetCellAlignment( (*it).x, (*it).y, ali, wxALIGN_CENTRE );
2848 k++;
2849 }
2850 } else { //use the passed selection, mode-dependent:
2851 if (disjointSelection) { //pairs lists
2852 for (SizeT n=0,l=0; n<selection->Dim(1); ++n) {
2853 int col = (*selection)[l++];
2854 int row = (*selection)[l++];
2855 int ali;
2856 switch ( (*table_alignment)[k % table_alignment->N_Elements( )] ) {
2857 case 0:
2858 ali = wxALIGN_LEFT;
2859 break;
2860 case 1:
2861 ali = wxALIGN_CENTRE;
2862 break;
2863 case 2:
2864 ali = wxALIGN_RIGHT;
2865 }
2866 grid->SetCellAlignment( row, col, ali, wxALIGN_CENTRE );
2867 k++;
2868 }
2869 }else{ //4 values
2870 int colTL = (*selection)[0];
2871 int rowTL = (*selection)[1];
2872 int colBR = (*selection)[2];
2873 int rowBR = (*selection)[3];
2874 for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j)
2875 {
2876 int ali;
2877 switch ( (*table_alignment)[k % table_alignment->N_Elements( )] ) {
2878 case 0:
2879 ali = wxALIGN_LEFT;
2880 break;
2881 case 1:
2882 ali = wxALIGN_CENTRE;
2883 break;
2884 case 2:
2885 ali = wxALIGN_RIGHT;
2886 }
2887 grid->SetCellAlignment( i, j, ali, wxALIGN_CENTRE );
2888 k++;
2889 }
2890 }
2891 }
2892 grid->EndBatch();
2893
2894 }
2895
DoBackgroundColor()2896 void GDLWidgetTable::DoBackgroundColor() {
2897 SizeT nbColors=backgroundColor->N_Elements( );
2898 if (nbColors==0) {return;}
2899 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2900 assert( grid != NULL);
2901 int nRows = grid->GetNumberRows( );
2902 int nCols = grid->GetNumberCols( );
2903 SizeT k=0;
2904 grid->BeginBatch();
2905 for (SizeT i=0; i< nRows; ++i) for (SizeT j=0; j< nCols; ++j) //Row by Row, from top.
2906 {
2907 grid->SetCellBackgroundColour( i, j, wxColour((*backgroundColor)[k%nbColors],(*backgroundColor)[k%nbColors+1],(*backgroundColor)[k%nbColors+2]));
2908 k+=3;
2909 }
2910 grid->EndBatch();
2911
2912 }
DoBackgroundColor(DLongGDL * selection)2913 void GDLWidgetTable::DoBackgroundColor(DLongGDL* selection) {
2914 SizeT nbColors=backgroundColor->N_Elements( );
2915 if (nbColors==0) {return;}
2916 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2917 assert( grid != NULL);
2918 grid->BeginBatch();
2919
2920 SizeT k=0;
2921
2922 if (selection->Rank()==0) { //use current wxWidgets selection
2923 std::vector<wxPoint> list=grid->GetSelectedDisjointCellsList();
2924 for ( std::vector<wxPoint>::iterator it = list.begin(); it !=list.end(); ++it) {
2925 grid->SetCellBackgroundColour( (*it).x, (*it).y, wxColour((*backgroundColor)[k%nbColors],(*backgroundColor)[k%nbColors+1],(*backgroundColor)[k%nbColors+2]));
2926 k+=3;
2927 }
2928 } else { //use the passed selection, mode-dependent:
2929 if (disjointSelection) { //pairs lists
2930 for (SizeT n=0,l=0; n<selection->Dim(1); ++n) {
2931 int col = (*selection)[l++];
2932 int row = (*selection)[l++];
2933 grid->SetCellBackgroundColour( row, col, wxColour((*backgroundColor)[k%nbColors],(*backgroundColor)[k%nbColors+1],(*backgroundColor)[k%nbColors+2]));
2934 k+=3;
2935 }
2936 }else{ //4 values
2937 int colTL = (*selection)[0];
2938 int rowTL = (*selection)[1];
2939 int colBR = (*selection)[2];
2940 int rowBR = (*selection)[3];
2941 for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j)
2942 {
2943 grid->SetCellBackgroundColour( i, j, wxColour((*backgroundColor)[k%nbColors],(*backgroundColor)[k%nbColors+1],(*backgroundColor)[k%nbColors+2]));
2944 k+=3;
2945 }
2946 }
2947 }
2948
2949 grid->EndBatch();
2950
2951 }
2952
DoForegroundColor()2953 void GDLWidgetTable::DoForegroundColor() {
2954 SizeT nbColors=foregroundColor->N_Elements( );
2955 if (nbColors==0) {return;}
2956 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2957 assert( grid != NULL);
2958 int nRows = grid->GetNumberRows( );
2959 int nCols = grid->GetNumberCols( );
2960 SizeT k=0;
2961 grid->BeginBatch();
2962 for (SizeT i=0; i< nRows; ++i) for (SizeT j=0; j< nCols; ++j) //Row by Row, from top.
2963 {
2964 grid->SetCellTextColour( i, j, wxColour((*foregroundColor)[k%nbColors],(*foregroundColor)[k%nbColors+1],(*foregroundColor)[k%nbColors+2]));
2965 k+=3;
2966 }
2967 grid->EndBatch();
2968
2969 }
2970
2971
DoForegroundColor(DLongGDL * selection)2972 void GDLWidgetTable::DoForegroundColor(DLongGDL* selection) {
2973 SizeT nbColors=foregroundColor->N_Elements( );
2974 if (nbColors==0) {return;}
2975 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
2976 assert( grid != NULL);
2977 grid->BeginBatch();
2978
2979 SizeT k=0;
2980
2981 if (selection->Rank()==0) { //use current wxWidgets selection
2982 std::vector<wxPoint> list=grid->GetSelectedDisjointCellsList();
2983 for ( std::vector<wxPoint>::iterator it = list.begin(); it !=list.end(); ++it) {
2984 grid->SetCellTextColour( (*it).x, (*it).y, wxColour((*foregroundColor)[k%nbColors],(*foregroundColor)[k%nbColors+1],(*foregroundColor)[k%nbColors+2]));
2985 k+=3;
2986 }
2987 } else { //use the passed selection, mode-dependent:
2988 if (disjointSelection) { //pairs lists
2989 for (SizeT n=0,l=0; n<selection->Dim(1); ++n) {
2990 int col = (*selection)[l++];
2991 int row = (*selection)[l++];
2992 grid->SetCellTextColour( row, col, wxColour((*foregroundColor)[k%nbColors],(*foregroundColor)[k%nbColors+1],(*foregroundColor)[k%nbColors+2]));
2993 k+=3;
2994 }
2995 }else{ //4 values
2996 int colTL = (*selection)[0];
2997 int rowTL = (*selection)[1];
2998 int colBR = (*selection)[2];
2999 int rowBR = (*selection)[3];
3000 for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j)
3001 {
3002 grid->SetCellTextColour( i, j, wxColour((*foregroundColor)[k%nbColors],(*foregroundColor)[k%nbColors+1],(*foregroundColor)[k%nbColors+2]));
3003 k+=3;
3004 }
3005 }
3006 }
3007
3008 grid->EndBatch();
3009
3010 }
3011
DoColumnLabels()3012 void GDLWidgetTable::DoColumnLabels( ) {
3013 if (columnLabels->N_Elements( )==0) {return;}
3014 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3015 assert( grid != NULL);
3016 int nCols = grid->GetNumberCols( );
3017 grid->BeginBatch();
3018 if ( columnLabels->N_Elements( ) == 1 ) { //singleton case
3019 if ( static_cast<DString> ((*columnLabels)[0]).length( ) == 0 ) {
3020 for ( SizeT j = 0; j < nCols; ++j ) grid->SetColLabelValue( j, wxEmptyString );
3021 } else {
3022 for ( SizeT j = 0; j < nCols; ++j ) {
3023 if ( j > (columnLabels->N_Elements( ) - 1) ) break;
3024 grid->SetColLabelValue( j, wxString( static_cast<DString> ((*columnLabels)[j]).c_str( ), wxConvUTF8 ) );
3025 }
3026 }
3027 } else {
3028 for ( SizeT j = 0; j < nCols; ++j ) {
3029 if ( j > (columnLabels->N_Elements( ) - 1) ) break;
3030 grid->SetColLabelValue( j, wxString( static_cast<DString> ((*columnLabels)[j]).c_str( ), wxConvUTF8 ) );
3031 }
3032 }
3033 grid->EndBatch();
3034
3035 }
3036
DoColumnWidth()3037 void GDLWidgetTable::DoColumnWidth( ) {
3038 if (columnWidth->N_Elements( )==0) {return;}
3039 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3040 assert( grid != NULL);
3041 int nCols = grid->GetNumberCols( );
3042 grid->BeginBatch();
3043 if ( columnWidth->N_Elements( ) == 1 ) for ( SizeT j = 0; j < nCols; ++j ) grid->SetColSize(j,(*columnWidth)[0]*unitConversionFactor.x);
3044 else {
3045 for ( SizeT j = 0; j < nCols; ++j ) {
3046 if ( j > (columnWidth->N_Elements( ) - 1) ) break;
3047 grid->SetColSize(j,(*columnWidth)[j]*unitConversionFactor.x);
3048 }
3049 }
3050 grid->EndBatch();
3051 }
3052
DoColumnWidth(DLongGDL * selection)3053 void GDLWidgetTable::DoColumnWidth( DLongGDL* selection ) {
3054 SizeT nbCols = columnWidth->N_Elements( );
3055 if ( nbCols == 0 ) {return;}
3056 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3057 assert( grid != NULL);
3058 grid->BeginBatch( );
3059
3060 SizeT k=0;
3061
3062 if ( selection->Rank( ) == 0 ) { //use current wxWidgets selection
3063 wxArrayInt list=grid->GetSortedSelectedColsList();
3064 //find concerned cols
3065 for ( int it = 0; it <list.GetCount(); ++it) {
3066 grid->SetColSize( list[it], (*columnWidth)[it % nbCols]*unitConversionFactor.x);
3067 }
3068 } else { //use the passed selection, mode-dependent:
3069 if (disjointSelection) { //pairs lists
3070 std::vector<int> allCols;
3071 std::vector<int>::iterator iter;
3072 //find concerned cols
3073 for ( SizeT n=0, l=0 ; n<selection->Dim(1); ++n) {
3074 int col = (*selection)[l++];l++;
3075 allCols.push_back(col);
3076 }
3077 std::sort (allCols.begin(), allCols.end());
3078 int theCol=-1;
3079 for ( iter = allCols.begin(); iter !=allCols.end(); ++iter) {
3080 if ((*iter)!=theCol) {
3081 theCol=(*iter);
3082 //if index is -1, we want to size the label column instead of the grid columns.
3083 if (theCol==-1) grid->SetRowLabelSize((*columnWidth)[k % nbCols]*unitConversionFactor.x);
3084 else if (theCol>=0 && theCol<grid->GetNumberCols()) grid->SetColSize( theCol, (*columnWidth)[k % nbCols]*unitConversionFactor.x );
3085 k++;
3086 }
3087 }
3088 } else { //4 values
3089 int colTL = (*selection)[0];
3090 int colBR = (*selection)[2];
3091 for (int j=colTL; j<=colBR; ++j)
3092 {
3093 //if index is -1, we want to size the label column instead of the grid columns.
3094 if (j==-1) grid->SetRowLabelSize((*columnWidth)[k % nbCols]*unitConversionFactor.x);
3095 else if (j>=0 && j<grid->GetNumberCols()) grid->SetColSize( j, (*columnWidth)[k % nbCols]*unitConversionFactor.x );
3096 k++;
3097 }
3098 }
3099 }
3100
3101 grid->EndBatch( );
3102 }
3103
GetColumnWidth(DLongGDL * selection)3104 DFloatGDL* GDLWidgetTable::GetColumnWidth(DLongGDL* selection){
3105 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3106 assert( grid != NULL);
3107 SizeT k=0;
3108 int nCols = grid->GetNumberCols( );
3109
3110 if ( selection == NULL) {
3111 DFloatGDL* res=new DFloatGDL(dimension(nCols));
3112 for ( SizeT j = 0; j < nCols; ++j ) (*res)[j]=grid->GetColSize(j);
3113 return res;
3114 } else if ( selection->Rank( ) == 0 ) { //use current wxWidgets selection
3115 wxArrayInt list=grid->GetSortedSelectedColsList();
3116 //find concerned cols
3117 if (list.GetCount()==0) return NULL;
3118 DFloatGDL* res=new DFloatGDL(dimension(list.GetCount()));
3119 for ( int it = 0; it <list.GetCount(); ++it) {
3120 (*res)[it]=grid->GetColSize( list[it] );
3121 }
3122 return res;
3123 } else { //use the passed selection, mode-dependent:
3124 if (disjointSelection) { //pairs lists
3125 std::vector<int> allCols;
3126 std::vector<int>::iterator iter;
3127 std::vector<int> theCols;
3128 //find concerned cols
3129 for ( SizeT n=0, l=0 ; n<selection->Dim(1); ++n) {
3130 int col = (*selection)[l++];l++;
3131 allCols.push_back(col);
3132 }
3133 std::sort (allCols.begin(), allCols.end());
3134 int theCol=-1;
3135 for ( iter = allCols.begin(); iter !=allCols.end(); ++iter) {
3136 if ((*iter)!=theCol) {
3137 theCol=(*iter);
3138 k++;
3139 theCols.push_back(theCol);
3140 }
3141 }
3142 //final list:
3143 if (theCols.size()==0) return NULL;
3144 DFloatGDL* res=new DFloatGDL(dimension(theCols.size()));
3145 for ( iter = theCols.begin(); iter !=theCols.end(); ++iter) {
3146 (*res)[k++]=grid->GetColSize( (*iter));
3147 }
3148 return res;
3149 } else { //4 values
3150 int colTL = (*selection)[0];
3151 int colBR = (*selection)[2];
3152 int count = colBR-colTL+1;
3153 if (count==0) return NULL;
3154 DFloatGDL* res=new DFloatGDL(dimension(count));
3155 for (int j=colTL; j<=colBR; ++j)
3156 {
3157 (*res)[k++]=grid->GetColSize(j);
3158 }
3159 }
3160 }
3161 return new DFloatGDL(0); //to keep compiler happy
3162 }
GetRowHeight(DLongGDL * selection)3163 DFloatGDL* GDLWidgetTable::GetRowHeight(DLongGDL* selection){
3164 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3165 assert( grid != NULL);
3166 SizeT k=0;
3167 int nRows = grid->GetNumberRows( );
3168
3169 if ( selection == NULL) {
3170 DFloatGDL* res=new DFloatGDL(dimension(nRows));
3171 for ( SizeT i = 0; i < nRows; ++i ) (*res)[i]=grid->GetRowSize(i);
3172 return res;
3173 } else if ( selection->Rank( ) == 0 ) { //use current wxWidgets selection
3174 wxArrayInt list=grid->GetSortedSelectedRowsList();
3175 //find concerned rows
3176 if (list.GetCount()==0) return NULL;
3177 DFloatGDL* res=new DFloatGDL(dimension(list.GetCount()));
3178 for ( int it = 0; it <list.GetCount(); ++it) {
3179 (*res)[it]=grid->GetRowSize( list[it] );
3180 }
3181 return res;
3182 } else { //use the passed selection, mode-dependent:
3183 if (disjointSelection) { //pairs lists
3184 std::vector<int> allRows;
3185 std::vector<int>::iterator iter;
3186 std::vector<int> theRows;
3187 //find concerned rows
3188 for ( SizeT n=0, l=0 ; n<selection->Dim(1); ++n) {
3189 int row = (*selection)[l++];l++;
3190 allRows.push_back(row);
3191 }
3192 std::sort (allRows.begin(), allRows.end());
3193 int theRow=-1;
3194 for ( iter = allRows.begin(); iter !=allRows.end(); ++iter) {
3195 if ((*iter)!=theRow) {
3196 theRow=(*iter);
3197 k++;
3198 theRows.push_back(theRow);
3199 }
3200 }
3201 //final list:
3202 if (theRows.size()==0) return NULL;
3203 DFloatGDL* res=new DFloatGDL(dimension(theRows.size()));
3204 for ( iter = theRows.begin(); iter !=theRows.end(); ++iter) {
3205 (*res)[k++]=grid->GetRowSize( (*iter));
3206 }
3207 return res;
3208 } else { //4 values
3209 int rowTL = (*selection)[1];
3210 int rowBR = (*selection)[3];
3211 int count = rowBR-rowTL+1;
3212 if (count==0) return NULL;
3213 DFloatGDL* res=new DFloatGDL(dimension(count));
3214 for (int j=rowTL; j<=rowBR; ++j)
3215 {
3216 (*res)[k++]=grid->GetRowSize(j);
3217 }
3218 }
3219 }
3220 return new DFloatGDL(0); //to keep compiler happy
3221 }
3222
DoRowHeights()3223 void GDLWidgetTable::DoRowHeights( ) {
3224 if (rowHeights->N_Elements( )==0) {return;}
3225 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3226 assert( grid != NULL);
3227 int nRows = grid->GetNumberRows( );
3228 grid->BeginBatch();
3229 if ( rowHeights->N_Elements( ) == 1 ) for ( SizeT i = 0; i < nRows; ++i ) grid->SetRowSize(i,(*rowHeights)[0]*unitConversionFactor.y);
3230 else {
3231 for ( SizeT i = 0; i < nRows; ++i ) {
3232 if ( i > (rowHeights->N_Elements( ) - 1) ) break;
3233 grid->SetRowSize(i,(*rowHeights)[i]*unitConversionFactor.y);
3234 }
3235 }
3236 grid->EndBatch();
3237 }
3238
DoRowHeights(DLongGDL * selection)3239 void GDLWidgetTable::DoRowHeights( DLongGDL* selection ) {
3240 SizeT nbRows = rowHeights->N_Elements( );
3241 if ( nbRows == 0 ) { return; }
3242 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3243 assert( grid != NULL);
3244 grid->BeginBatch( );
3245
3246 SizeT k=0;
3247
3248 if ( selection->Rank( ) == 0 ) { //use current wxWidgets selection
3249 wxArrayInt list=grid->GetSortedSelectedRowsList();
3250 for ( int it = 0; it <list.GetCount(); ++it) {
3251 if (list[it]<grid->GetNumberRows()) grid->SetRowSize( list[it], (*rowHeights)[it % nbRows]*unitConversionFactor.y );
3252 }
3253 } else { //use the passed selection, mode-dependent:
3254 if (disjointSelection) { //pairs lists
3255 std::vector<int> allRows;
3256 std::vector<int>::iterator iter;
3257 for ( SizeT n=0, l=0 ; n<selection->Dim(1); ++n) {
3258 l++;
3259 int row = (*selection)[l++];
3260 allRows.push_back(row);
3261 }
3262 std::sort (allRows.begin(), allRows.end());
3263 int theRow=-1;
3264 for ( iter = allRows.begin(); iter !=allRows.end(); ++iter) {
3265 if ((*iter)!=theRow) {
3266 theRow=(*iter);
3267 //if index is -1, we want to size the label column instead of the grid columns.
3268 if (theRow==-1) grid->SetColLabelSize((*columnWidth)[k % nbRows]*unitConversionFactor.x);
3269 else if (theRow>=0 && theRow<grid->GetNumberRows()) grid->SetRowSize( theRow, (*rowHeights)[k % nbRows] *unitConversionFactor.y);
3270 k++;
3271 }
3272 }
3273 } else { //4 values
3274 int rowTL = (*selection)[1];
3275 int rowBR = (*selection)[3];
3276 for (int i=rowTL; i<=rowBR; ++i)
3277 {
3278 //if index is -1, we want to size the label column instead of the grid columns.
3279 if (i==-1) grid->SetColLabelSize((*columnWidth)[k % nbRows]*unitConversionFactor.x);
3280 else if (i>=0 && i<grid->GetNumberRows()) grid->SetRowSize( i, (*rowHeights)[k % nbRows]*unitConversionFactor.y );
3281 k++;
3282 }
3283 }
3284 }
3285
3286 grid->EndBatch( );
3287 }
3288
DoRowLabels()3289 void GDLWidgetTable::DoRowLabels( ) {
3290 if (rowLabels->N_Elements( )==0) {return;}
3291 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3292 assert( grid != NULL);
3293 int nRows = grid->GetNumberRows( );
3294 grid->BeginBatch();
3295 if ( rowLabels->N_Elements( ) == 1 ) { //singleton case
3296 if ( static_cast<DString> ((*rowLabels)[0]).length( ) == 0 ) {
3297 for ( SizeT i = 0; i < nRows; ++i ) grid->SetRowLabelValue( i, wxEmptyString );
3298 } else {
3299 for ( SizeT i = 0; i < nRows; ++i ) {
3300 if ( i > (rowLabels->N_Elements( ) - 1) ) break;
3301 grid->SetRowLabelValue( i, wxString( static_cast<DString> ((*rowLabels)[i]).c_str( ), wxConvUTF8 ) );
3302 }
3303 }
3304 } else {
3305 for ( SizeT i = 0; i < nRows; ++i ) {
3306 if ( i > (rowLabels->N_Elements( ) - 1) ) break;
3307 grid->SetRowLabelValue( i, wxString( static_cast<DString> ((*rowLabels)[i]).c_str( ), wxConvUTF8 ) );
3308 }
3309 }
3310 grid->EndBatch();
3311 }
3312
DeleteColumns(DLongGDL * selection)3313 void GDLWidgetTable::DeleteColumns(DLongGDL* selection) {
3314 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3315 assert( grid != NULL);
3316 grid->BeginBatch( );
3317
3318 if ( selection==NULL || selection->Rank( ) == 0 ) { //use current wxWidgets selection
3319 wxArrayInt list=grid->GetSortedSelectedColsList();
3320 //delete in reverse order to avoid column-numbering problems
3321 for ( int it = list.GetCount()-1; it >-1 ; --it) {
3322 grid->DeleteCols( list[it], 1, true);
3323 }
3324 } else { //use the passed selection, mode-dependent:
3325 if (disjointSelection) { //pairs lists
3326 std::vector<int> allCols;
3327 std::vector<int>::reverse_iterator riter;
3328 //find concerned cols
3329 for ( SizeT n=0, l=0 ; n<selection->Dim(1); ++n) {
3330 int col = (*selection)[l++];l++;
3331 allCols.push_back(col);
3332 }
3333 std::sort (allCols.begin(), allCols.end());
3334 int theCol=-1;
3335 for ( riter = allCols.rbegin(); riter !=allCols.rend(); ++riter) {
3336 if ((*riter)!=theCol) {
3337 theCol=(*riter);
3338 grid->DeleteCols( theCol, 1, true);
3339 }
3340 }
3341 } else { //4 values, cols are contiguous, easy.
3342 int colTL = (*selection)[0];
3343 int colBR = (*selection)[2];
3344 int count=colBR-colTL+1;
3345 grid->DeleteCols( colTL , count, true );
3346 }
3347 }
3348
3349 grid->EndBatch( );
3350 }
InsertColumns(DLong count,DLongGDL * selection)3351 bool GDLWidgetTable::InsertColumns(DLong count, DLongGDL* selection) {
3352 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3353 assert( grid != NULL);
3354 bool success;
3355 grid->BeginBatch( );
3356
3357 if ( selection==NULL ){ //add count to rightmost position
3358 int pos=grid->GetNumberCols();
3359 success=grid->InsertCols(pos,count,true);
3360 // Set new grid cell contents TBD FIXME!
3361 {SizeT k=0; for (SizeT i=0; i< grid->GetNumberRows(); ++i) for (SizeT j=pos; j<grid->GetNumberCols() ; ++j) {grid->SetCellValue( i, j, wxString( "0" , wxConvUTF8 ) );++k;}}
3362 }
3363 else if (selection->Rank( ) == 0 ) { //add left of current wxWidgets selection
3364 wxArrayInt list=grid->GetSortedSelectedColsList();
3365 //insert to left of first one
3366 success=grid->InsertCols( list[0], count, true);
3367 } else { //use the passed selection, mode-dependent:
3368 if (disjointSelection) { //pairs lists
3369 std::vector<int> allCols;
3370 //find concerned cols
3371 for ( SizeT n=0, l=0 ; n<selection->Dim(1); ++n) {
3372 int col = (*selection)[l++];l++;
3373 allCols.push_back(col);
3374 }
3375 std::sort (allCols.begin(), allCols.end());
3376 success=grid->InsertCols( *(allCols.begin()), 1, true);
3377 } else { //4 values, cols are contiguous, easy.
3378 int colTL = (*selection)[0];
3379 success=grid->InsertCols( colTL , count, true );
3380 }
3381 }
3382
3383 grid->EndBatch( );
3384 return success;
3385 }
3386
DeleteRows(DLongGDL * selection)3387 void GDLWidgetTable::DeleteRows(DLongGDL* selection) {
3388 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3389 assert( grid != NULL);
3390 grid->BeginBatch( );
3391
3392 if ( selection==NULL || selection->Rank( ) == 0 ) { //use current wxWidgets selection
3393 wxArrayInt list=grid->GetSortedSelectedRowsList();
3394 //delete in reverse order to avoid column-numbering problems
3395 for ( int it = list.GetCount()-1; it >-1 ; --it) {
3396 grid->DeleteRows( list[it], 1, true);
3397 }
3398 } else { //use the passed selection, mode-dependent:
3399 if (disjointSelection) { //pairs lists
3400 std::vector<int> allRows;
3401 std::vector<int>::reverse_iterator riter;
3402 //find concerned Rows
3403 for ( SizeT n=0, l=0 ; n<selection->Dim(1); ++n) {
3404 int row = (*selection)[l++];l++;
3405 allRows.push_back(row);
3406 }
3407 std::sort (allRows.begin(), allRows.end());
3408 int theRow=-1;
3409 for ( riter = allRows.rbegin(); riter !=allRows.rend(); ++riter) {
3410 if ((*riter)!=theRow) {
3411 theRow=(*riter);
3412 grid->DeleteRows( theRow, 1, true);
3413 }
3414 }
3415 } else { //4 values, Rows are contiguous, easy.
3416 int rowTL = (*selection)[1];
3417 int rowBR = (*selection)[3];
3418 int count=rowBR-rowTL+1;
3419 grid->DeleteRows( rowTL , count, true );
3420 }
3421 }
3422
3423 grid->EndBatch( );
3424 }
3425
InsertRows(DLong count,DLongGDL * selection)3426 bool GDLWidgetTable::InsertRows(DLong count, DLongGDL* selection) {
3427 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3428 assert( grid != NULL);
3429 bool success;
3430 grid->BeginBatch( );
3431
3432 if ( selection==NULL ){ //add count to rightmost position
3433 int pos=grid->GetNumberRows();
3434 success=grid->InsertRows(pos,count,true);
3435 // Set new grid cell contents TBD FIXME!
3436 {SizeT k=0; for (SizeT i=pos; i<grid->GetNumberRows(); ++i) for (SizeT j=0; j<grid->GetNumberCols() ; ++j) {grid->SetCellValue( i, j, wxString( "0" , wxConvUTF8 ) );++k;}}
3437 }
3438 else if (selection->Rank( ) == 0 ) { //add left of current wxWidgets selection
3439 wxArrayInt list=grid->GetSortedSelectedRowsList();
3440 //insert to left of first one
3441 success=grid->InsertRows( list[0], count, true);
3442 } else { //use the passed selection, mode-dependent:
3443 if (disjointSelection) { //pairs lists
3444 std::vector<int> allRows;
3445 //find concerned rows
3446 for ( SizeT n=0, l=0 ; n<selection->Dim(1); ++n) {
3447 int row = (*selection)[l++];l++;
3448 allRows.push_back(row);
3449 }
3450 std::sort (allRows.begin(), allRows.end());
3451 success=grid->InsertRows( *(allRows.begin()), 1, true);
3452 } else { //4 values, cols are contiguous, easy.
3453 int rowTL = (*selection)[1];
3454 success=grid->InsertRows( rowTL , count, true );
3455 }
3456 }
3457
3458 grid->EndBatch( );
3459 return success;
3460 }
3461
SetTableValues(DStringGDL * val,DLongGDL * selection)3462 void GDLWidgetTable::SetTableValues(DStringGDL* val, DLongGDL* selection)
3463 {
3464 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3465 assert( grid != NULL);
3466
3467 grid->BeginBatch();
3468
3469 if ( selection==NULL ){ //reset table to everything. val replaces valueAsStrings.
3470 GDLDelete(valueAsStrings);
3471 valueAsStrings=val->Dup();
3472 SizeT numRows,numCols;
3473 if (valueAsStrings->Rank()==1) {
3474 numRows=1;
3475 numCols=valueAsStrings->Dim(0); //lines
3476 } else {
3477 numRows=valueAsStrings->Dim(1);
3478 numCols=valueAsStrings->Dim(0);
3479 }
3480 grid->ClearGrid();
3481 int curr_rows=grid->GetNumberRows();
3482 int curr_cols=grid->GetNumberCols();
3483 //adjust rows and cols:
3484 if (numRows > curr_rows) grid->AppendRows(numRows-curr_rows);
3485 if (numCols > curr_cols) grid->AppendCols(numCols-curr_cols);
3486 // Set grid cell contents as strings
3487 {SizeT k=0; for (SizeT i=0; i<numRows ; ++i) for (SizeT j=0; j< numCols; ++j) {grid->SetCellValue( i, j, wxString(((*valueAsStrings)[k]).c_str(), wxConvUTF8 ) );++k;}}
3488
3489 } else { //use the wxWidget selection or the passed selection, mode-dependent:
3490 if (disjointSelection) { //pairs lists
3491 if (selection->Rank()==0) {
3492 std::vector<wxPoint> list=grid->GetSelectedDisjointCellsList();
3493 SizeT k=0;
3494 for (std::vector<wxPoint>::iterator it = list.begin(); it !=list.end(); ++it) {
3495 grid->SetCellValue( (*it).x, (*it).y ,wxString(((*val)[k++]).c_str(), wxConvUTF8 ) );
3496 if (k==val->N_Elements()) break;
3497 }
3498 } else {
3499 for (SizeT k=0,n=0,l=0; n<selection->Dim(1); ++n) {
3500 int col = (*selection)[l++];
3501 int row = (*selection)[l++];
3502 grid->SetCellValue( row, col ,wxString(((*val)[k++]).c_str(), wxConvUTF8 ) );
3503 if (k==val->N_Elements()) break;
3504 }
3505 }
3506 } else { //IDL maintains the 2D-structure of val!
3507 SizeT numRows,numCols;
3508 if (val->Rank()==1) {
3509 numRows=1;
3510 numCols=val->Dim(0); //lines
3511 } else {
3512 numRows=val->Dim(1);
3513 numCols=val->Dim(0);
3514 }
3515 int colTL,colBR,rowTL,rowBR;
3516 if (selection->Rank()==0) {
3517 wxArrayInt block=grid->GetSelectedBlockOfCells();
3518 //normally only ONE block is available.
3519 colTL = block[0];
3520 rowTL = block[1];
3521 colBR = block[2];
3522 rowBR = block[3];
3523 } else {
3524 colTL = (*selection)[0];
3525 rowTL = (*selection)[1];
3526 colBR = (*selection)[2];
3527 rowBR = (*selection)[3];
3528 }
3529 for ( int ival=0, i=rowTL; i<=rowBR; ++i, ++ival) for (int jval=0, j=colTL; j<=colBR; ++j, ++jval)
3530 {
3531 if (ival < numRows && jval < numCols ) grid->SetCellValue( i, j ,wxString(((*val)[jval*numRows+ival]).c_str(), wxConvUTF8 ) );
3532 }
3533 }
3534 }
3535 grid->EndBatch( );
3536 }
GetTableValuesAsStruct(DLongGDL * selection)3537 BaseGDL* GDLWidgetTable::GetTableValuesAsStruct(DLongGDL* selection)
3538 {
3539 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3540 assert( grid != NULL);
3541 BaseGDL* res;
3542 int numRows=valueAsStrings->Dim(0);
3543 int numCols=valueAsStrings->Dim(1);
3544 DStringGDL* stringres=this->GetTableValues(selection);
3545 if (stringres==NULL) return NULL; //pass error back.
3546
3547 if ( selection==NULL ){ //just convert
3548 res=vValue->Dup();
3549 stringstream is;
3550 // if (majority == GDLWidgetTable::ROW_MAJOR ) {
3551 // BaseGDL* tmp=static_cast<BaseGDL*>(stringres)->Transpose(NULL);
3552 // GDLDelete(stringres);
3553 // stringres=static_cast<DStringGDL*>(tmp);
3554 // for( SizeT i = 0; i < stringres->N_Elements(); i++) is << (*stringres)[ i] << '\n';
3555 // } else {
3556 for( SizeT i = 0; i < stringres->N_Elements(); i++) is << (*stringres)[ i] << '\n';
3557 // }
3558 res->FromStream( is);
3559 }
3560 else { //use the wxWidget selection or the passed selection, mode-dependent:
3561 if (disjointSelection) { //pairs lists
3562 std::vector<wxPoint> list;
3563 if (selection->Rank()==0) { //use current wxWidgets selection. Result is a STRUCT
3564 list=grid->GetSelectedDisjointCellsList();
3565 } else { //make equivalent vector.
3566 for (SizeT k=0,n=0,l=0; n<selection->Dim(1); ++n) {
3567 int col = (*selection)[l++];
3568 int row = (*selection)[l++];
3569 list.push_back(wxPoint(row,col));
3570 }
3571 }
3572 SizeT k=0;
3573 DStructGDL* typecodes = new DStructGDL( "GDL_TYPECODES_AS_STRUCT");
3574 // creating the output anonymous structure
3575 DStructDesc* res_desc = new DStructDesc("$truct");
3576 for ( std::vector<wxPoint>::iterator it = list.begin(); it !=list.end(); ++it, ++k) {
3577 //get tag values:
3578 BaseGDL* tested;
3579 if (majority == GDLWidgetTable::ROW_MAJOR )
3580 tested=static_cast<DStructGDL*>(vValue)->GetTag((*it).y); //table columns are tags
3581 else
3582 tested=static_cast<DStructGDL*>(vValue)->GetTag((*it).x); //table rows are tags
3583 stringstream os;
3584 os << std::setfill ('_') << std::setw (12) << k ; //as IDL does
3585 std::string tagName;
3586 os >> tagName;
3587 res_desc->AddTag(tagName, typecodes->GetTag(tested->Type()));
3588 }
3589 stringstream is;
3590 for( SizeT i = 0; i < stringres->N_Elements(); i++) is << (*stringres)[ i] << '\n';
3591 res = new DStructGDL(res_desc, dimension());
3592 res->FromStream( is);
3593 } else { //IDL maintains the 2D-structure of val!
3594 int colTL,colBR,rowTL,rowBR;
3595 if (selection->Rank()==0) {
3596 wxArrayInt block=grid->GetSelectedBlockOfCells();
3597 //normally only ONE block is available.
3598 colTL = block[0];
3599 rowTL = block[1];
3600 colBR = block[2];
3601 rowBR = block[3];
3602 } else {
3603 colTL = (*selection)[0];
3604 rowTL = (*selection)[1];
3605 colBR = (*selection)[2];
3606 rowBR = (*selection)[3];
3607 }
3608 //complication: if only one row (col) is selected, result is an array of <type>.
3609 //else result is a structure with correct tag names. Very clever!
3610 if ((majority == GDLWidgetTable::ROW_MAJOR && colTL==colBR)||(majority == GDLWidgetTable::COLUMN_MAJOR && rowTL==rowBR)) {
3611 DType what=GDL_BYTE;
3612 SizeT size;
3613 if (majority == GDLWidgetTable::ROW_MAJOR && colTL==colBR) {
3614 what=static_cast<DStructGDL*>(vValue)->GetTag(colTL)->Type();
3615 size=rowBR-rowTL+1;
3616 } else if (rowTL==rowBR) {
3617 what=static_cast<DStructGDL*>(vValue)->GetTag(rowTL)->Type();
3618 size=colBR-colTL+1;
3619 }
3620 switch(what) {
3621 case GDL_STRING:
3622 res=new DStringGDL(dimension(size));
3623 break;
3624 case GDL_BYTE:
3625 res=new DByteGDL(dimension(size));
3626 break;
3627 case GDL_INT:
3628 res=new DIntGDL(dimension(size));
3629 break;
3630 case GDL_LONG:
3631 res=new DLongGDL(dimension(size));
3632 break;
3633 case GDL_FLOAT:
3634 res=new DFloatGDL(dimension(size));
3635 break;
3636 case GDL_DOUBLE:
3637 res=new DDoubleGDL(dimension(size));
3638 break;
3639 case GDL_COMPLEX:
3640 res=new DComplexGDL(dimension(dimension(size)));
3641 break;
3642 case GDL_COMPLEXDBL:
3643 res=new DComplexDblGDL(dimension(size));
3644 break;
3645 case GDL_UINT:
3646 res=new DUIntGDL(dimension(size));
3647 break;
3648 case GDL_ULONG:
3649 res=new DULongGDL(dimension(size));
3650 break;
3651 case GDL_LONG64:
3652 res=new DLong64GDL(dimension(size));
3653 break;
3654 case GDL_ULONG64:
3655 res=new DULong64GDL(dimension(size));
3656 break;
3657 default:
3658 cerr<<"Unhandled Table Type, please report!"<<endl;
3659 return NULL; //signal error
3660 }
3661 } else { //create dedicated struct
3662 DStructGDL* typecodes = new DStructGDL( "GDL_TYPECODES_AS_STRUCT");
3663 // creating the output anonymous structure
3664 DStructDesc* res_desc = new DStructDesc("$truct");
3665 SizeT size;
3666 if (majority == GDLWidgetTable::ROW_MAJOR) { //data is in rows of structures. Columns are tags
3667 size=rowBR-rowTL+1;
3668 for (SizeT j=colTL; j<=colBR; ++j) {
3669 //get tag values:
3670 BaseGDL* tested;
3671 std::string tagName;
3672 tested=static_cast<DStructGDL*>(vValue)->GetTag(j);
3673 tagName=static_cast<DStructGDL*>(vValue)->Desc()->TagName(j); //preserve tag names
3674 res_desc->AddTag(tagName, typecodes->GetTag(tested->Type()));
3675 }
3676 } else {
3677 size=colBR-colTL+1;
3678 for (SizeT i=rowTL; i<=rowBR; ++i) {
3679 //get tag values:
3680 BaseGDL* tested;
3681 std::string tagName;
3682 tested=static_cast<DStructGDL*>(vValue)->GetTag(i);
3683 tagName=static_cast<DStructGDL*>(vValue)->Desc()->TagName(i); //preserve tag names
3684 res_desc->AddTag(tagName, typecodes->GetTag(tested->Type()));
3685 }
3686 }
3687 //create res with correct dim:
3688 res = new DStructGDL(res_desc, dimension(size));
3689 }
3690 //populate res:
3691 stringstream is;
3692 for( SizeT i = 0; i < stringres->N_Elements(); i++) is << (*stringres)[ i] << '\n';
3693 res->FromStream( is);
3694 }
3695 }
3696 return res;
3697 }
3698
GetTableValues(DLongGDL * selection)3699 DStringGDL* GDLWidgetTable::GetTableValues(DLongGDL* selection)
3700 {
3701 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3702 assert( grid != NULL);
3703
3704 DStringGDL * stringres;
3705 int numRows=valueAsStrings->Dim(0);
3706 int numCols=valueAsStrings->Dim(1);
3707
3708 if ( selection==NULL ){
3709 int ncols=grid->GetNumberCols();
3710 int nrows=grid->GetNumberCols();
3711
3712 SizeT dims[2];
3713 dims[1]=(nrows>numRows)?numRows:nrows;
3714 dims[0]=(ncols>numCols)?numCols:ncols;
3715 dimension dim(dims,2);
3716 stringres=new DStringGDL(dim);
3717
3718 for ( int ival=0, i=0; i<nrows; ++i, ++ival) for (int jval=0, j=0; j<ncols; ++j, ++jval)
3719 {
3720 if (ival < numRows && jval < numCols ) (*stringres)[jval*numRows+ival]= grid->GetCellValue( i, j).mb_str(wxConvUTF8);
3721 }
3722 } else { //use the wxWidget selection or the passed selection, mode-dependent:
3723 if (disjointSelection) { //pairs lists
3724 if (selection->Rank()==0) { //use current wxWidgets selection
3725 std::vector<wxPoint> list=grid->GetSelectedDisjointCellsList();
3726 stringres=new DStringGDL(list.size());
3727 SizeT k=0;
3728 for ( std::vector<wxPoint>::iterator it = list.begin(); it !=list.end(); ++it) {
3729 if ((*it).x >= numRows || (*it).y >= numCols) return static_cast<DStringGDL*>(NULL);
3730 (*stringres)[k++]=grid->GetCellValue( (*it).x, (*it).y ).mb_str(wxConvUTF8);
3731 }
3732 } else {
3733 stringres=new DStringGDL(selection->Dim(1));
3734 for (SizeT k=0,n=0,l=0; n<selection->Dim(1); ++n) {
3735 int col = (*selection)[l++];
3736 int row = (*selection)[l++];
3737 if ( row >= numRows || col >= numCols) return static_cast<DStringGDL*>(NULL);
3738 (*stringres)[k++]=grid->GetCellValue( row, col).mb_str(wxConvUTF8);
3739 }
3740 }
3741 } else { //IDL maintains the 2D-structure of val!
3742 int colTL,colBR,rowTL,rowBR;
3743 if (selection->Rank()==0) {
3744 wxArrayInt block=grid->GetSelectedBlockOfCells();
3745 //normally only ONE block is available.
3746 colTL = block[0];
3747 rowTL = block[1];
3748 colBR = block[2];
3749 rowBR = block[3];
3750 } else {
3751 colTL = (*selection)[0];
3752 rowTL = (*selection)[1];
3753 colBR = (*selection)[2];
3754 rowBR = (*selection)[3];
3755 }
3756 SizeT dims[2];
3757 dims[1]=(rowBR-rowTL+1);
3758 dims[0]=(colBR-colTL+1);
3759 dimension dim(dims,2);
3760 stringres=new DStringGDL(dim);
3761 for (SizeT k=0,i=rowTL; i<=rowBR; ++i) for (SizeT j=colTL; j<=colBR; ++j)
3762 {
3763 if ( i >= numRows || j >= numCols) return static_cast<DStringGDL*>(NULL);
3764 (*stringres)[k++]=grid->GetCellValue(i, j).mb_str(wxConvUTF8);
3765 }
3766 }
3767 }
3768 //convention: if value is of type struct, string array will always be row_major. thus if we are column major, transpose return string array
3769 if (vValue->Type()==GDL_STRUCT && majority==GDLWidgetTable::COLUMN_MAJOR) return static_cast<DStringGDL*>(stringres->Transpose(NULL))->Dup();
3770 else return stringres;
3771 }
3772
SetSelection(DLongGDL * selection)3773 void GDLWidgetTable::SetSelection(DLongGDL* selection)
3774 {
3775 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3776 assert( grid != NULL);
3777 grid->BeginBatch( );
3778 updating=true; //prevent sending unwanted events
3779 grid->ClearSelection();
3780 wxPoint firstVisible=wxPoint(0,0);
3781 if (disjointSelection) { //pairs lists
3782 SizeT k=0;
3783 for (SizeT i=0; i< selection->Dim(1); ++i) {
3784 int col=(*selection)[k++];
3785 int row=(*selection)[k++];
3786 grid->SelectBlock(row,col,row,col,true);
3787 if (k==2) {firstVisible.x=row;firstVisible.y=col;}
3788 }
3789 } else {
3790 int colTL = (*selection)[0];
3791 int rowTL = (*selection)[1];
3792 int colBR = (*selection)[2];
3793 int rowBR = (*selection)[3];
3794 grid->SelectBlock(rowTL,colTL,rowBR,colBR,false);
3795 firstVisible.x=rowTL;firstVisible.y=colTL;
3796 }
3797 grid->EndBatch( );
3798 grid->MakeCellVisible(firstVisible.x,firstVisible.y);
3799 updating=false; //allow events
3800 }
SetTableView(DLongGDL * pos)3801 void GDLWidgetTable::SetTableView(DLongGDL* pos)
3802 {
3803 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3804 assert( grid != NULL);
3805 grid->MakeCellVisible((*pos)[1],(*pos)[0]);
3806 }
EditCell(DLongGDL * pos)3807 void GDLWidgetTable::EditCell(DLongGDL* pos)
3808 {
3809 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3810 assert( grid != NULL);
3811 grid->SetReadOnly((*pos)[0],(*pos)[1],false);
3812 }
SetTableNumberOfColumns(DLong ncols)3813 void GDLWidgetTable::SetTableNumberOfColumns( DLong ncols){
3814 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3815 assert( grid != NULL);
3816 grid->BeginBatch( );
3817 int old_ncols=grid->GetNumberCols();
3818 int numRows=valueAsStrings->Dim(0);
3819 int numCols=valueAsStrings->Dim(1);
3820 if (ncols > old_ncols) {
3821 grid->AppendCols(ncols-old_ncols);
3822 if (numCols > old_ncols) {
3823 int colTL,colBR,rowTL,rowBR;
3824 colTL=old_ncols-1;
3825 colBR=ncols-1;
3826 rowTL=0;
3827 rowBR=grid->GetNumberRows()-1;
3828 for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j)
3829 {
3830 if (i < numRows && j < numCols ) grid->SetCellValue( i, j ,wxString(((*valueAsStrings)[j*numRows+i]).c_str(), wxConvUTF8 ) );
3831 }
3832 }
3833 }
3834 else if (ncols < old_ncols) grid->DeleteCols(ncols,old_ncols-ncols);
3835 grid->EndBatch( );
3836 }
SetTableNumberOfRows(DLong nrows)3837 void GDLWidgetTable::SetTableNumberOfRows( DLong nrows){
3838 wxGridGDL * grid = dynamic_cast<wxGridGDL*> (theWxWidget);
3839 assert( grid != NULL);
3840 grid->BeginBatch( );
3841 SizeT old_nrows=grid->GetNumberRows();
3842 int numRows=valueAsStrings->Dim(0);
3843 int numCols=valueAsStrings->Dim(1);
3844 if (nrows > old_nrows) {
3845 grid->AppendRows(nrows-old_nrows);
3846 if (numRows > old_nrows) {
3847 int colTL,colBR,rowTL,rowBR;
3848 colTL=0;
3849 colBR=grid->GetNumberCols()-1;
3850 rowTL=old_nrows-1;
3851 rowBR=nrows-1;
3852 for ( int i=rowTL; i<=rowBR; ++i) for (int j=colTL; j<=colBR; ++j)
3853 {
3854 if (i < numRows && j < numCols ) grid->SetCellValue( i, j ,wxString(((*valueAsStrings)[j*numRows+i]).c_str(), wxConvUTF8 ) );
3855 }
3856 }
3857 }
3858 else if (nrows < old_nrows) grid->DeleteRows(nrows,old_nrows-nrows);
3859 grid->EndBatch( );
3860 }
GetGeometry(wxRealPoint fact)3861 DStructGDL* GDLWidgetTable::GetGeometry(wxRealPoint fact)
3862 {
3863 if (!this->IsRealized()) this->Realize(true,false);//necessary if a geometry request is done previous to the command widget_control,xxx,,/Realize !
3864 GDLWidgetBase* container = static_cast<GDLWidgetBase*> (this->GetMyParent());
3865 assert(container != NULL);
3866 int ixsize = 0, iysize = 0, iscr_xsize = 0, iscr_ysize = 0;
3867 DFloat xsize = 0;
3868 DFloat ysize = 0;
3869 DFloat scr_xsize = 0;
3870 DFloat scr_ysize = 0;
3871 DFloat xoffset = 0;
3872 DFloat yoffset = 0;
3873 DFloat margin = 0;
3874
3875 DStructGDL* ex = new DStructGDL("WIDGET_GEOMETRY");
3876
3877 wxWindow* test = dynamic_cast<wxWindow*> (theWxContainer);
3878 if (test==NULL) return ex;
3879 wxRect r=test->GetRect();
3880 xoffset = r.x ;
3881 yoffset = r.y ;
3882 wxGrid* w = dynamic_cast<wxGrid*> (theWxWidget);
3883 if (w==NULL) return ex;
3884 wxRect z=w->GetRect();
3885
3886 iscr_xsize = z.width;
3887 iscr_ysize = z.height;
3888 wxSize s=w->GetClientSize();
3889 ixsize = s.x;
3890 iysize = s.y;
3891
3892 if (theWxWidget == theWxContainer) margin=0; else {
3893 margin=(r.width-z.width)/2; //Rect is about the container, which is the widgetPanel and not the frame depending on case.
3894 }
3895 //size is in columns
3896 int rowsize=w->GetRowSize(0);
3897 int rowlabelsize=w->GetRowLabelSize();
3898 int colsize=w->GetColSize(0);
3899 int collabelsize=w->GetColLabelSize();
3900 xsize = (ixsize-rowlabelsize) / colsize ;
3901 ysize = (iysize-collabelsize) / rowsize ;
3902
3903 scr_xsize = iscr_xsize / fact.x;
3904 scr_ysize = iscr_ysize / fact.y;
3905 xoffset /= fact.x;
3906 yoffset /= fact.y;
3907 margin /= fact.x;
3908
3909 ex->InitTag("XOFFSET", DFloatGDL(xoffset));
3910 ex->InitTag("YOFFSET", DFloatGDL(yoffset));
3911 ex->InitTag("XSIZE", DFloatGDL(xsize));
3912 ex->InitTag("YSIZE", DFloatGDL(ysize));
3913 ex->InitTag("SCR_XSIZE", DFloatGDL(scr_xsize));
3914 ex->InitTag("SCR_YSIZE", DFloatGDL(scr_ysize));
3915 ex->InitTag("MARGIN", DFloatGDL(margin));
3916
3917 return ex;
3918 }
3919
setFont()3920 void GDLWidgetTable::setFont() {
3921 wxGrid* g = dynamic_cast<wxGrid*> (this->GetWxWidget());
3922 if (g != NULL) {
3923 if (!font.IsSameAs(wxNullFont)) {
3924 g->SetLabelFont(font);
3925 g->SetDefaultCellFont(font);
3926 } else {
3927 g->SetLabelFont(defaultFont);
3928 g->SetDefaultCellFont(defaultFont);
3929 }
3930 }
3931 }
~GDLWidgetTable()3932 GDLWidgetTable::~GDLWidgetTable()
3933 {
3934 #ifdef GDL_DEBUG_WIDGETS
3935 std::cout << "~GDLWidgetTable(" << widgetID << ")" << std::endl;
3936 #endif
3937 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
3938
3939 GDLDelete( table_alignment );
3940 GDLDelete( editable );
3941 GDLDelete( amPm );
3942 GDLDelete( backgroundColor );
3943 GDLDelete( foregroundColor );
3944 GDLDelete( columnLabels );
3945 GDLDelete( columnWidth );
3946 GDLDelete( daysOfWeek );
3947 GDLDelete( format );
3948 GDLDelete( month );
3949 GDLDelete( rowHeights );
3950 GDLDelete( rowLabels );
3951 GDLDelete( valueAsStrings );
3952 }
3953
3954 /*********************************************************/
3955 // for WIDGET_TREE
3956 /*********************************************************/
3957
GDLWidgetTree(WidgetIDT p,EnvT * e,BaseGDL * value_,DULong eventFlags_,wxBitmap * bitmap,DLong dragability,DLong dropability,bool expanded_,bool folder_,DLong treeindex,DString & dragNotify_)3958 GDLWidgetTree::GDLWidgetTree( WidgetIDT p, EnvT* e, BaseGDL* value_, DULong eventFlags_
3959 ,wxBitmap* bitmap
3960 ,DLong dragability
3961 ,DLong dropability
3962 ,bool expanded_
3963 ,bool folder_
3964 ,DLong treeindex
3965 ,DString &dragNotify_
3966 )
3967 : GDLWidget( p, e, value_, eventFlags_ )
3968 ,droppable(dropability ) //inherited
3969 ,draggable(dragability ) //inherited
3970 ,expanded(expanded_)
3971 ,myRoot(NULL)
3972 ,treeItemData(NULL)
3973 ,has_checkbox(false)
3974 ,folder(folder_)
3975 ,mask(false)
3976 ,dragNotify( dragNotify_)
3977 {
3978
3979 //checkbox is inherited
3980
3981 static int CHECKBOX = e->KeywordIx("CHECKBOX");
3982 static int CHECKED = e->KeywordIx("CHECKED");
3983 bool checkbox_asked = false;
3984 if (e->KeywordPresent(CHECKBOX)){
3985 checkbox_asked = true;
3986 DLong value=0;
3987 e->AssureLongScalarKWIfPresent(CHECKBOX,value);
3988 has_checkbox = (value>0);
3989 }
3990 bool checked = (has_checkbox && e->KeywordSet(CHECKED));
3991
3992 GDLWidget* gdlParent = GetWidget( parentID );
3993 widgetPanel = GetParentPanel( );
3994 widgetSizer = GetParentSizer( );
3995 DStringGDL* value=static_cast<DStringGDL*>(vValue);
3996
3997 //define the base tree widget globally here
3998 wxTreeCtrlGDL* myTreeRoot;
3999 if ( gdlParent->IsBase( ) ) {
4000 folder=true; //IS A FOLDER!
4001 static int NO_BITMAPS = e->KeywordIx("NO_BITMAPS");
4002 noBitmaps = e->KeywordSet(NO_BITMAPS);
4003 static int MULTIPLE = e->KeywordIx("MULTIPLE");
4004 multiple = e->KeywordSet(MULTIPLE);
4005
4006 wxImageList *stateImages = gdlDefaultTreeStateImages;
4007 wxImageList *images = gdlDefaultTreeImages;
4008 START_ADD_EVENTUAL_FRAME
4009
4010 // a tree widget is always inside a scrolled window, whose ScrollSize is 200 pixels by default
4011 if ( wSize.x <= 0 ) wSize.x = 200; //yes, has a default value!
4012 if ( wSize.y <= 0 ) wSize.y = 200;
4013
4014 wSize=computeWidgetSize( ); //this is a SetClientSize
4015
4016 long style = wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT|wxTR_HIDE_ROOT; //OK
4017 if (multiple) style |= wxTR_MULTIPLE; //widget is insensitive, FIXME
4018 //we have no root, create one.
4019 myTreeRoot = new wxTreeCtrlGDL(widgetPanel, widgetID, wxDefaultPosition, wxDefaultSize, style );
4020 theWxContainer = theWxWidget = myTreeRoot;
4021 //All lists are set always. Checkboxes will be hidden if checkbox is not present
4022 myTreeRoot->SetImageList(images);
4023 myTreeRoot->SetStateImageList(stateImages);
4024
4025 myRoot=this;
4026 treeItemData=new wxTreeItemDataGDL(widgetID, myTreeRoot);
4027 // if (bitmap) {
4028 // int index=images->Add(*bitmap);
4029 // treeItemID = tree->AddRoot(wxString( (*value)[0].c_str( ), wxConvUTF8 ), index ,-1, treeItemData);
4030 // } else { //use open and closed folder icons
4031 treeItemID = myTreeRoot->AddRoot(wxString( (*value)[0].c_str( ), wxConvUTF8 ), 0 ,1, treeItemData);
4032 // }
4033 // tree->SetItemImage(treeItemID,(folder)?(expanded?gdlWxTree_FOLDER_OPEN:gdlWxTree_FOLDER):gdlWxTree_ITEM);
4034 // checkbox is not visible for root// if (has_checkbox) tree->SetItemState(treeItemID,(checked==true)); else tree->SetItemState(treeItemID,wxTREE_ITEMSTATE_NONE); //CHECKED,UNCHECKE,NOT_VISIBLE
4035 widgetStyle=widgetAlignment( );
4036 if (dropability == -1) droppable=0; //this for root only
4037 if (dragability == -1) draggable=0; //this for root only
4038 if (dragNotify=="<inherit>") dragNotify="<default>";
4039 //do not expand root if hidden: will assert() in wxWidgets! // if (expanded) tree->Expand(treeItemID);
4040 myTreeRoot->SetClientSize(wSize);
4041 myTreeRoot->SetMinClientSize(wSize);
4042 // tree->ShowScrollbars(wxSHOW_SB_ALWAYS,wxSHOW_SB_ALWAYS); //possibly useful.
4043 END_ADD_EVENTUAL_FRAME
4044 TIDY_WIDGET(gdlBORDER_SPACE)
4045
4046 //does not work, fixme. Replaced by global setting in gdlwidgeteventhandler
4047 // this->AddToDesiredEvents(wxEVT_COMMAND_TREE_ITEM_ACTIVATED,wxTreeEventHandler(wxTreeCtrlGDL::OnItemActivated),myTreeRoot);
4048 // this->AddToDesiredEvents(wxEVT_COMMAND_TREE_BEGIN_DRAG,wxTreeEventHandler(wxTreeCtrlGDL::OnBeginDrag),myTreeRoot);
4049 // this->AddToDesiredEvents(wxEVT_COMMAND_TREE_END_DRAG,wxTreeEventHandler(wxTreeCtrlGDL::OnItemDropped),myTreeRoot);
4050 // this->AddToDesiredEvents(wxEVT_COMMAND_TREE_ITEM_COLLAPSED,wxTreeEventHandler(wxTreeCtrlGDL::OnItemCollapsed),myTreeRoot);
4051 // this->AddToDesiredEvents(wxEVT_COMMAND_TREE_ITEM_EXPANDED,wxTreeEventHandler(wxTreeCtrlGDL::OnItemExpanded),myTreeRoot);
4052 // this->AddToDesiredEvents(wxEVT_COMMAND_TREE_SEL_CHANGED,wxTreeEventHandler(wxTreeCtrlGDL::OnItemSelected),myTreeRoot);
4053
4054 } else {
4055 // static int TOOLTIP = e->KeywordIx( "TOOLTIP" );
4056 // DString toolTip;
4057 // e->AssureStringScalarKWIfPresent( TOOLTIP, toolTip );
4058
4059 GDLWidgetTree* parentTree = static_cast<GDLWidgetTree*> (gdlParent);
4060 assert( parentTree != NULL);
4061 theWxWidget = parentTree->GetWxWidget( );
4062 myRoot = parentTree->GetMyRootGDLWidgetTree();
4063 bool nobitmaps=myRoot->IsUsingBitmaps();
4064
4065 myTreeRoot = dynamic_cast<wxTreeCtrlGDL*> (theWxWidget);
4066 assert( myTreeRoot != NULL);
4067 treeItemData=new wxTreeItemDataGDL(widgetID,myTreeRoot);
4068 theWxContainer=NULL; //this is not a widget
4069
4070 //if parent has checkbox, I have a checkbox too unless has_checkbox is false
4071 bool parent_has_checkbox=parentTree->HasCheckBox();
4072 if (!checkbox_asked) has_checkbox=(parent_has_checkbox);
4073 //if treeindex is present, it must be < the number of children (otherwise baoum, thank you wxWidgets)
4074 if (treeindex > -1 ) {
4075 //possible?
4076 if (parentTree->IsFolder()) {
4077 unsigned int count = myTreeRoot->GetChildrenCount(parentTree->treeItemID, false);
4078 if (treeindex >= count) treeindex = count;
4079 } else e->Throw("Parent tree widget is not a folder.");
4080 }
4081 if (nobitmaps) {
4082 if (treeindex > -1 ) treeItemID = myTreeRoot->InsertItem( parentTree->treeItemID, treeindex, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,-1,-1, treeItemData);
4083 else treeItemID = myTreeRoot->AppendItem( parentTree->treeItemID, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,-1,-1, treeItemData);
4084 }
4085 else if (bitmap) {
4086 //images (default vs. custom: problem of sizes: wxWidgets ENFORCES an uniform scaling)
4087 int imindex=myTreeRoot->GetImageList()->Add(wxBitmap((*bitmap).ConvertToImage().Rescale(DEFAULT_TREE_IMAGE_SIZE,DEFAULT_TREE_IMAGE_SIZE)));
4088 if (treeindex > -1 ) treeItemID = myTreeRoot->InsertItem( parentTree->treeItemID, treeindex, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,imindex,imindex, treeItemData);
4089 else treeItemID = myTreeRoot->AppendItem( parentTree->treeItemID, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,imindex,imindex, treeItemData);
4090 } else { //since no image is a bit disappointing use our internal wxWigdets icons
4091 if (folder) { //use open and closed folder icons
4092 if (treeindex > -1 ) treeItemID = myTreeRoot->InsertItem( parentTree->treeItemID, treeindex, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,TREE_BITMAP_FOLDER,TREE_BITMAP_FOLDER_OPEN, treeItemData);
4093 else treeItemID = myTreeRoot->AppendItem( parentTree->treeItemID, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,TREE_BITMAP_FOLDER,TREE_BITMAP_FOLDER_OPEN, treeItemData);
4094 } //or normal file
4095 else if (treeindex > -1) treeItemID = myTreeRoot->InsertItem( parentTree->treeItemID, treeindex, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,TREE_BITMAP_ITEM,TREE_BITMAP_ITEM_SELECTED, treeItemData);
4096 else treeItemID = myTreeRoot->AppendItem( parentTree->treeItemID, wxString( (*value)[0].c_str( ), wxConvUTF8 ) ,TREE_BITMAP_ITEM,TREE_BITMAP_ITEM_SELECTED, treeItemData);
4097 }
4098
4099 if (has_checkbox) myTreeRoot->SetItemState(treeItemID,(checked==true)); else myTreeRoot->SetItemState(treeItemID,wxTREE_ITEMSTATE_NONE); //CHECKED,UNCHECKE,NOT_VISIBLE
4100 //expand if requested:
4101 if (expanded) {
4102 myTreeRoot->SetItemHasChildren( treeItemID, true); //TRICK! to enable folder opened or closed BY CONSTRUCTION.
4103 DoExpand(true);
4104 }
4105 // if (tooltip) DO SOMETHING! FIXME.
4106 if (this->IsRealized()){
4107 myTreeRoot->Refresh();
4108 }
4109 }
4110
4111
4112 // UPDATE_WINDOW
4113 REALIZE_IF_NEEDED
4114 }
GetDropability()4115 bool GDLWidgetTree::GetDropability() {
4116 int enabledrop=droppable;
4117 GDLWidgetTree* root=myRoot;
4118 GDLWidgetTree* w=this;
4119 while (enabledrop < 0 && w!=root) {
4120 w=static_cast<GDLWidgetTree*>(w->GetMyParent());
4121 enabledrop=w->GetDroppableValue();
4122 }
4123 return (enabledrop == 1);
4124 }
GetDragability()4125 bool GDLWidgetTree::GetDragability() {
4126 int enabledrag=draggable;
4127 GDLWidgetTree* root=myRoot;
4128 GDLWidgetTree* w=this;
4129 while (enabledrag < 0 && w!=root) {
4130 w=static_cast<GDLWidgetTree*>(w->GetMyParent());
4131 enabledrag=w->GetDraggableValue();
4132 }
4133 return (enabledrag == 1);
4134 }
DoExpand(bool what)4135 void GDLWidgetTree::DoExpand(bool what){
4136 expanded=what;
4137 if (what) treeItemData->myTree->Expand(treeItemID); else treeItemData->myTree->Collapse(treeItemID);
4138 treeItemData->myTree->Refresh();
4139 }
Select(bool select)4140 void GDLWidgetTree::Select(bool select){
4141 if (this->myRoot->GetWidgetID() != widgetID ) treeItemData->myTree->SelectItem(treeItemID,select); //root is not selectable
4142 treeItemData->myTree->Refresh();
4143 }
SetTreeIndex(DLong where)4144 void GDLWidgetTree::SetTreeIndex(DLong where) {
4145 GDLWidgetTree* parentTree = static_cast<GDLWidgetTree*> (GetWidget( parentID ));
4146 if (parentTree->IsFolder()){ //is Folder
4147 wxTreeCtrlGDL* myTreeRoot=dynamic_cast<wxTreeCtrlGDL*> (theWxWidget);
4148 assert( myTreeRoot != NULL);
4149 wxTreeItemId currentId = this->treeItemID;
4150 //where should i put it?
4151 unsigned int count = myTreeRoot->GetChildrenCount(parentTree->treeItemID, false);
4152 DLong treeindex=count;
4153 if (where > -1 && where <= treeindex) treeindex =where; //will start putting at 'treeindex'
4154 wxString s=myTreeRoot->GetItemText(currentId);
4155 int imindex=myTreeRoot->GetItemImage(currentId);
4156 wxTreeItemId newId=myTreeRoot->InsertItem( parentTree->treeItemID, treeindex, s ,imindex,imindex, treeItemData);
4157 //we heve to suppress treeItemData from where it was previously attached otherwise it will be destroyed and bang!
4158 myTreeRoot->SetItemData(currentId,NULL);
4159 if (this->HasCheckBox()) myTreeRoot->SetItemState(newId,this->IsChecked()); // else myTreeRoot->SetItemState(treeItemID,wxTREE_ITEMSTATE_NONE); //CHECKED,UNCHECKE,NOT_VISIBLE
4160 if (expanded) {
4161 myTreeRoot->SetItemHasChildren( newId, true); //TRICK! to enable folder opened or closed BY CONSTRUCTION.
4162 myTreeRoot->Expand(newId);
4163 }
4164 // give back treeItemID to transferred GDLTreeWidget:
4165 this->SetItemID(newId);
4166 //Children?
4167 count = myTreeRoot->GetChildrenCount(currentId,false);
4168 if (count == 0) {
4169 myTreeRoot->Delete(currentId);
4170 return;
4171 }
4172 //build full list of children, call this on each GDLWidgetTree:
4173 wxArrayTreeItemIds list;
4174 wxTreeItemIdValue cookie;
4175 wxTreeItemId id = myTreeRoot->GetFirstChild(currentId, cookie);
4176 do {
4177 list.Add(id);
4178 id = myTreeRoot->GetNextSibling(id);
4179 } while (id.IsOk());
4180 int nb=list.Count();
4181 for (int i=0; i< count ; ++i) {
4182 id=list[i];
4183 wxTreeItemDataGDL* d=static_cast<wxTreeItemDataGDL*>(myTreeRoot->GetItemData(id));
4184 static_cast<GDLWidgetTree*>(GDLWidget::GetWidget(d->widgetID))->SetTreeIndex(-1); //added at the end
4185 }
4186 myTreeRoot->Delete(currentId);
4187 myTreeRoot->Refresh();
4188 } //else throw GDLException("Parent tree widget is not a folder."); //IDL just forgets.
4189 }
OnRealize()4190 void GDLWidgetTree::OnRealize(){
4191 GDLWidgetTree* root=this->GetMyRootGDLWidgetTree();
4192 if (this==root) {
4193 wxTreeCtrlGDL* ctrl=static_cast<wxTreeCtrlGDL*>(this->GetWxWidget());
4194 wxTreeItemId id=ctrl->GetFirstVisibleItem ( ) ;
4195 if (id) ctrl->SetFocusedItem(id);
4196 }
4197 }
GetTreeIndex()4198 DInt GDLWidgetTree::GetTreeIndex()
4199 {
4200 DInt count=0;
4201 wxTreeCtrlGDL* tree=dynamic_cast<wxTreeCtrlGDL*>(theWxWidget);
4202 assert( tree != NULL);
4203 wxTreeItemId id=this->treeItemID;
4204 wxTreeItemId prev_id=tree->GetPrevSibling(id);
4205 while (prev_id.IsOk()){
4206 count++;
4207 id=prev_id;
4208 prev_id=tree->GetPrevSibling(id);
4209 }
4210 return count;
4211 }
4212
~GDLWidgetTree()4213 GDLWidgetTree::~GDLWidgetTree()
4214 {
4215 #ifdef GDL_DEBUG_WIDGETS
4216 std::cout << "~GDLWidgetTree: (" << widgetID <<")"<< std::endl;
4217 #endif
4218 //the wxWidget points to the parent branch. A leaf has wxContainer=NULL. //If we are on a leaf, set thewxWidget to NULL at the end, as it would be doubly destroyed in ~GDLWidget otherwise.
4219
4220 wxTreeCtrlGDL* tree = dynamic_cast<wxTreeCtrlGDL*> (theWxWidget);
4221 if (tree) { // container-type behaviour: kill gdl childrens
4222 wxTreeItemId id = this->treeItemID;
4223 if (id.IsOk()) {
4224 wxTreeItemIdValue cookie;
4225 wxTreeItemId child = tree->GetFirstChild(id, cookie);
4226 while (child.IsOk()) {
4227 WidgetIDT childID = dynamic_cast<wxTreeItemDataGDL*> (tree->GetItemData(child))->widgetID;
4228 GDLWidgetTree* GDLchild = static_cast<GDLWidgetTree*> (GDLWidget::GetWidget(childID));
4229 child = tree->GetNextSibling(child); //nextChild did not find the last (?) nextSibling does the job.
4230 #ifdef GDL_DEBUG_WIDGETS
4231 std::cout << "~GDLWidgetTree, deleting item ID #" << childID << " of tree widget #" << widgetID << std::endl;
4232 #endif
4233 delete GDLchild;
4234 }
4235 treeItemID.Unset();
4236 tree->Delete(id);
4237 }
4238 tree->Refresh();
4239 }
4240 //after all children destroyed, destroy my wx counterpart
4241 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
4242 }
4243
SetValue(DString val)4244 void GDLWidgetTree::SetValue(DString val)
4245 {
4246 GDLDelete(vValue);
4247 vValue=new DStringGDL(val);
4248 wxTreeCtrlGDL* tree=dynamic_cast<wxTreeCtrlGDL*>(theWxWidget);
4249 assert( tree != NULL);
4250 tree->SetItemText(treeItemID, wxString( val.c_str( ), wxConvUTF8 ));
4251 tree->Refresh();
4252 }
4253
SetBitmap(wxBitmap * bitmap)4254 void GDLWidgetTree::SetBitmap(wxBitmap* bitmap) {
4255 //images (default vs. custom: problem of sizes: wxWidgets ENFORCES an uniform scaling)
4256 wxTreeCtrlGDL* myTreeRoot=treeItemData->myTree;
4257 wxBitmap b=wxBitmap((*bitmap).ConvertToImage().Rescale(DEFAULT_TREE_IMAGE_SIZE, DEFAULT_TREE_IMAGE_SIZE));
4258 int myimindex = myTreeRoot->GetItemImage(treeItemID, wxTreeItemIcon_Normal);
4259 if (myimindex < TREE_BITMAP_END) { //this is a 'default' image, do not overwrite, add a new one
4260 int imindex=myTreeRoot->GetImageList()->Add(b);
4261 for (wxTreeItemIcon i=wxTreeItemIcon_Normal; i< wxTreeItemIcon_Max; i=wxTreeItemIcon(i+1)) myTreeRoot->SetItemImage(treeItemID,imindex,i);
4262 } else {
4263 myTreeRoot->GetImageList()->Replace(myimindex,b);
4264 }
4265 myTreeRoot->Refresh();
4266 }
4267
ReturnBitmapAsBytes()4268 DByteGDL* GDLWidgetTree::ReturnBitmapAsBytes() {
4269 wxTreeCtrlGDL* myTreeRoot = treeItemData->myTree;
4270 int myimindex = myTreeRoot->GetItemImage(treeItemID, wxTreeItemIcon_Normal);
4271 if (myimindex < TREE_BITMAP_END) { //this is a 'default' image,return 0
4272 return new DByteGDL(0);
4273 } else {
4274 wxImage image=myTreeRoot->GetImageList()->GetBitmap(myimindex).ConvertToImage().Mirror(false); //Mirror=FlIP necessary!!!
4275 unsigned char* pixels=image.GetData();
4276 wxSize sz=image.GetSize();
4277 DByteGDL* res=new DByteGDL(dimension(sz.x,sz.y,3), BaseGDL::NOZERO); //in fact [3,N,M] RGBRGB...
4278 SizeT k=0;
4279 SizeT jump=sz.x*sz.y;
4280 for (SizeT i=0; i< sz.x*sz.y; ++i) {(*res)[i]=pixels[k++];(*res)[i+jump]=pixels[k++]; (*res)[i+2*jump]=pixels[k++];}//[N,M,3]
4281 return res;
4282 }
4283 }
4284
IsSelectedID()4285 WidgetIDT GDLWidgetTree::IsSelectedID() {
4286 return treeItemData->myTree->IsSelected(treeItemID);
4287 }
4288
IsDragSelectedID()4289 WidgetIDT GDLWidgetTree::IsDragSelectedID() { //must return
4290 wxTreeItemId test = treeItemID;
4291 wxTreeCtrlGDL* myTreeRoot = treeItemData->myTree;
4292 if (!myTreeRoot->IsSelected(test)) return 0;
4293 do {
4294 test = myTreeRoot->GetItemParent(test);
4295 } while (test.IsOk() && !myTreeRoot->IsSelected(test));
4296 if (!test.IsOk()) {
4297 return 1; //no parent was selected
4298 }
4299 return 0;
4300 }
4301
GetAllSelectedID()4302 DLongGDL* GDLWidgetTree::GetAllSelectedID() {
4303 //tree must be root
4304 GDLWidgetTree* myGdlTreeRoot = this->GetMyRootGDLWidgetTree();
4305 assert(myGdlTreeRoot == this);
4306 wxTreeCtrlGDL* myTreeRoot = treeItemData->myTree;
4307 wxArrayTreeItemIds list;
4308 int nb = myTreeRoot->GetSelections(list);
4309 if (nb == 0) return new DLongGDL(-1);
4310 DLongGDL* res = new DLongGDL(dimension(nb), BaseGDL::NOZERO);
4311 for (int i = 0; i < nb; ++i) {
4312 wxTreeItemDataGDL* data = static_cast<wxTreeItemDataGDL*> (myTreeRoot->GetItemData(list[i]));
4313 (*res)[i] = data->GetWidgetID();
4314 }
4315 return res;
4316 }
4317 //called with root tree only. As soon as a folder is selected, childrens must not be returned as they are supposed to be 'included' in whatever action
4318 //is done with this list.
GetAllDragSelectedID()4319 DLongGDL* GDLWidgetTree::GetAllDragSelectedID(){
4320 //tree must be root
4321 GDLWidgetTree* myGdlTreeRoot = this->GetMyRootGDLWidgetTree();
4322 assert(myGdlTreeRoot==this);
4323 wxTreeCtrlGDL* myTreeRoot = treeItemData->myTree;
4324 wxArrayTreeItemIds list1;
4325 int nb = myTreeRoot->GetSelections(list1);
4326 if (nb == 0) return new DLongGDL(-1);
4327 wxArrayTreeItemIds list2;
4328 for (int i = 0; i < nb; ++i) { //test whether itemid's list of parent is selected. if one parent is lecetd, drop it else add in list2.
4329 wxTreeItemId test=list1[i];
4330 do {
4331 test=myTreeRoot->GetItemParent(test);
4332 } while (test.IsOk() && !myTreeRoot->IsSelected(test));
4333 if (!test.IsOk()) {
4334 list2.Add(list1[i]); //no parent was selected
4335 }
4336 }
4337 nb=list2.Count();
4338 if (nb == 0) return new DLongGDL(-1);
4339 DLongGDL* res = new DLongGDL(dimension(nb), BaseGDL::NOZERO);
4340 for (int i = 0; i < nb; ++i) {
4341 wxTreeItemDataGDL* data = static_cast<wxTreeItemDataGDL*> (myTreeRoot->GetItemData(list2[i]));
4342 (*res)[i] = data->GetWidgetID();
4343 }
4344 return res;
4345 }
4346
4347
NChildren() const4348 DLong GDLWidgetTree::NChildren() const {
4349 wxTreeCtrlGDL* myTreeRoot=treeItemData->myTree;
4350 return myTreeRoot->GetChildrenCount(treeItemID,false);
4351 }
GetChild(DLong childIx) const4352 WidgetIDT GDLWidgetTree::GetChild(DLong childIx) const { //childIx is not used here
4353 wxTreeCtrlGDL* myTreeRoot=treeItemData->myTree;
4354 wxTreeItemIdValue cookie;
4355 wxTreeItemId id=myTreeRoot->GetFirstChild(treeItemID,cookie);
4356 if (!id.IsOk()) return 0;
4357 return static_cast<wxTreeItemDataGDL*>(myTreeRoot->GetItemData(id))->widgetID;
4358 }
GetChildrenList() const4359 DLongGDL* GDLWidgetTree::GetChildrenList() const {
4360 wxTreeCtrlGDL* myTreeRoot=treeItemData->myTree;
4361 int n=myTreeRoot->GetChildrenCount(treeItemID,false);
4362 if (n<1) return new DLongGDL(0);
4363 wxTreeItemIdValue cookie;
4364 DLongGDL* ret=new DLongGDL(dimension(n),BaseGDL::NOZERO);
4365 wxTreeItemId id=myTreeRoot->GetFirstChild(treeItemID,cookie);
4366 (*ret)[0]=static_cast<wxTreeItemDataGDL*>(myTreeRoot->GetItemData(id))->widgetID;
4367 for (int i=1; i<n; ++i) {
4368 id=myTreeRoot->GetNextChild(treeItemID,cookie);
4369 assert (id.IsOk());
4370 (*ret)[i]=static_cast<wxTreeItemDataGDL*>(myTreeRoot->GetItemData(id))->widgetID;
4371 }
4372 return ret;
4373 }
GetTheSiblingOf(DLong myId)4374 DLong GDLWidgetTree::GetTheSiblingOf(DLong myId) { //GetTheSibling is called by widget_info() using the parent widget (a container). This is not our case here.
4375 // retrieve My infos, not parent's:
4376 GDLWidgetTree* me=static_cast<GDLWidgetTree*>(GDLWidget::GetWidget(myId));
4377 if (me==NULL) return 0; else return me->Sibling(); //call Sibling with good 'this'
4378 }
Sibling()4379 DLong GDLWidgetTree::Sibling() { //uses NextSibling, which may be 0.
4380 wxTreeCtrlGDL* myTreeRoot=treeItemData->myTree;
4381 wxTreeItemId id=myTreeRoot->GetNextSibling(treeItemID);
4382 if (!id.IsOk()) return 0;
4383 return static_cast<wxTreeItemDataGDL*>(myTreeRoot->GetItemData(id))->widgetID;
4384 }
4385 /*********************************************************/
4386 // for WIDGET_SLIDER
4387 /*********************************************************/
GDLWidgetSlider(WidgetIDT p,EnvT * e,DLong value_,DULong eventFlags_,DLong minimum_,DLong maximum_,bool vertical,bool suppressValue,DString & title_)4388 GDLWidgetSlider::GDLWidgetSlider( WidgetIDT p, EnvT* e, DLong value_
4389 , DULong eventFlags_
4390 , DLong minimum_
4391 , DLong maximum_
4392 , bool vertical
4393 , bool suppressValue
4394 , DString &title_ )
4395 : GDLWidget( p, e, NULL, eventFlags_ )
4396 , value( value_ ) //should disappear , duplicates vValue!
4397 , minimum( minimum_ )
4398 , maximum( maximum_ )
4399 , title( title_)
4400 {
4401 GDLWidget* gdlParent = GetWidget( parentID );
4402 widgetPanel = GetParentPanel( );
4403 widgetSizer = GetParentSizer( );
4404
4405 START_ADD_EVENTUAL_FRAME
4406
4407 if (( wSize.x <= 0 ) && !vertical) wSize.x=100; //yes, has a default value!
4408 if (( wSize.y <= 0 ) && vertical) wSize.y=100;
4409
4410 long style = wxSL_HORIZONTAL;
4411 if ( vertical ) style = wxSL_VERTICAL;
4412 if ( !suppressValue ) {
4413 #if wxCHECK_VERSION(2,9,1)
4414 style |= wxSL_VALUE_LABEL;
4415 #else
4416 style |= wxSL_LABELS;
4417 #endif
4418 }
4419
4420 widgetStyle=widgetAlignment();
4421 const wxString s=wxString( title.c_str( ), wxConvUTF8 );
4422 wxSlider* slider;
4423
4424 //get defined sizes if any
4425 wSize=computeWidgetSize( );
4426 // this is the size in absence of text:
4427 wxSize slidersize=(vertical)?wxSize(-1,wSize.y):wxSize(wSize.x,-1);
4428 bool hastitle=(s.size()>0);
4429 //// A gdlSlider is a comboPanel containing a wxStaticText (eventually) plus a slider.
4430 //if text or frame, we need a panel containing the wxVERTICAL association. frame is sunken if /FRAME, or NONE
4431 if (hastitle) {
4432 wxPanel* comboPanel=new wxPanel(widgetPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
4433 wxSizer* combosz = new wxBoxSizer(wxVERTICAL);
4434 comboPanel->SetSizer(combosz);
4435 theWxContainer = comboPanel; //else stays as panel_if_framed.
4436 comboPanel->SetFont(font); //enable fancy font
4437 //little difficulty: insure that combo widget size is correct in presence of (fancy) text.
4438 int w=0;
4439 int h=0;
4440 int d=0;
4441 int lead=0;
4442 comboPanel->GetTextExtent(s,&w,&h,&d,&lead,&font);
4443 slidersize=(vertical)?wxSize(-1,wSize.y-h-3*gdlSPACE):wxSize(max(wSize.x,w),-1);
4444 slider= new wxSlider( comboPanel, widgetID, value, minimum, maximum, wxDefaultPosition, wxDefaultSize, style);
4445 slider->SetSize(slidersize);
4446 slider->SetMinSize(slidersize);
4447 combosz->Add(slider,DONOTALLOWSTRETCH,wxEXPAND) ; //wxALL|(vertical)?wxALIGN_CENTRE_HORIZONTAL:widgetStyle,gdlSPACE);
4448 wxStaticText *theTitle=new wxStaticText(comboPanel,wxID_ANY,s);
4449 combosz->Add(theTitle,DONOTALLOWSTRETCH,widgetStyle|wxALL,gdlSPACE);
4450 combosz->AddSpacer(5);
4451 comboPanel->Fit();
4452 theWxWidget=comboPanel; //to trick ADD EVENTUAL FRAME
4453 } else {
4454 slider= new wxSlider( widgetPanel, widgetID, value, minimum, maximum, wxDefaultPosition, wxDefaultSize, style);
4455 slider->SetSize(slidersize);
4456 slider->SetMinSize(slidersize);
4457 theWxContainer = theWxWidget=slider;
4458 widgetPanel->Fit();
4459 }
4460
4461 END_ADD_EVENTUAL_FRAME
4462 theWxWidget=slider; //no trick anymore!
4463 TIDY_WIDGET(gdlBORDER_SPACE)
4464 // UPDATE_WINDOW
4465 REALIZE_IF_NEEDED
4466 this->AddToDesiredEvents( wxEVT_SCROLL_CHANGED,wxScrollEventHandler(gdlwxFrame::OnThumbRelease),slider);
4467 //dynamically select drag, saves resources! (note: there is no widget_control,/drag for sliders)
4468 if ( eventFlags & GDLWidget::EV_DRAG ) this->AddToDesiredEvents( wxEVT_SCROLL_THUMBTRACK,wxScrollEventHandler(gdlwxFrame::OnThumbTrack),slider);
4469 }
ControlSetValue(DLong v)4470 void GDLWidgetSlider::ControlSetValue(DLong v){
4471 value=v;
4472 wxSlider* s=dynamic_cast<wxSlider*>(theWxWidget);
4473 assert( s != NULL);
4474 s->SetValue(v);
4475 }
4476
ControlSetMinValue(DLong v)4477 void GDLWidgetSlider::ControlSetMinValue(DLong v) {
4478 value = v;
4479 wxSlider* s = dynamic_cast<wxSlider*> (theWxWidget);
4480 assert(s != NULL);
4481 s->SetRange(v, s->GetMax());
4482 }
4483
ControlSetMaxValue(DLong v)4484 void GDLWidgetSlider::ControlSetMaxValue(DLong v) {
4485 value = v;
4486 wxSlider* s = dynamic_cast<wxSlider*> (theWxWidget);
4487 assert(s != NULL);
4488 s->SetRange(s->GetMin(),v);
4489 }
4490
~GDLWidgetSlider()4491 GDLWidgetSlider::~GDLWidgetSlider(){
4492 title.clear();
4493 #ifdef GDL_DEBUG_WIDGETS
4494 std::cout << "~GDLWidgetSlider(" << widgetID <<")"<< std::endl;
4495 #endif
4496 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
4497 }
4498
GDLWidgetButton(WidgetIDT p,EnvT * e,DStringGDL * value,DULong eventflags,wxBitmap * bitmap_)4499 GDLWidgetButton::GDLWidgetButton( WidgetIDT p, EnvT* e,
4500 DStringGDL* value , DULong eventflags, wxBitmap* bitmap_)
4501 : GDLWidget( p, e, value, eventflags )
4502 , buttonType( UNDEFINED )
4503 , buttonBitmap(bitmap_)
4504 , buttonState(false)
4505 , menuItem(NULL)
4506 , valueWxString( wxString((*value)[0].c_str(), wxConvUTF8) )
4507 {
4508 if (valueWxString.Length() < 1) valueWxString=wxT(" ");
4509 }
4510
4511
~GDLWidgetButton()4512 GDLWidgetButton::~GDLWidgetButton() {
4513 #ifdef GDL_DEBUG_WIDGETS
4514 std::cout << "~GDLWidgetButton(" << widgetID << ")" << std::endl;
4515 #endif
4516 if (buttonBitmap) delete buttonBitmap;
4517 }
4518
4519 //a normal button.
GDLWidgetNormalButton(WidgetIDT p,EnvT * e,DStringGDL * value,DULong eventflags,wxBitmap * bitmap_,DStringGDL * buttonToolTip)4520 GDLWidgetNormalButton::GDLWidgetNormalButton(WidgetIDT p, EnvT* e,
4521 DStringGDL* value, DULong eventflags, wxBitmap* bitmap_, DStringGDL* buttonToolTip)
4522 : GDLWidgetButton(p, e, value, eventflags, bitmap_)
4523 {
4524 GDLWidget* gdlParent = GetWidget(parentID);
4525 widgetPanel = GetParentPanel();
4526 widgetSizer = GetParentSizer();
4527
4528 START_ADD_EVENTUAL_FRAME
4529
4530 widgetStyle = widgetAlignment();
4531 wSize = computeWidgetSize();
4532 long style=wxBORDER_NONE;
4533 //we deliberately prevent exclusive buttons when bitmap are present (exclusive buttons w/ pixmap do not exist in wxWidgets.
4534 if (gdlParent->GetExclusiveMode() == BGNORMAL || bitmap_) {
4535 if (bitmap_) {
4536 wxBitmapButton *button = new wxBitmapButton(widgetPanel, widgetID, *bitmap_, wxDefaultPosition, wxDefaultSize, style);
4537 theWxContainer = theWxWidget = button;
4538 buttonType = BITMAP;
4539 this->AddToDesiredEvents(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gdlwxFrame::OnButton), button);
4540 } else {
4541 wxButton *button = new wxButton(widgetPanel, widgetID, valueWxString,wxDefaultPosition, wxDefaultSize, buttonTextAlignment());
4542 theWxContainer = theWxWidget = button;
4543 buttonType = NORMAL;
4544 this->AddToDesiredEvents(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(gdlwxFrame::OnButton), button);
4545 }
4546 } else if (gdlParent->GetExclusiveMode() == BGEXCLUSIVE1ST) {
4547 wxRadioButton *radioButton = new wxRadioButton(widgetPanel, widgetID, valueWxString, wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
4548 gdlParent->SetExclusiveMode(1);
4549 GDLWidgetBase* b = static_cast<GDLWidgetBase*> (gdlParent);
4550 if (b) b->SetLastRadioSelection(widgetID);
4551 else cerr << "Warning GDLWidgetNormalButton::GDLWidgetNormalButton(): widget type confusion(1)\n";
4552
4553 theWxContainer = theWxWidget = radioButton;
4554 this->AddToDesiredEvents(wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler(gdlwxFrame::OnRadioButton), radioButton);
4555 buttonType = RADIO;
4556 } else if (gdlParent->GetExclusiveMode() == BGEXCLUSIVE) {
4557 wxRadioButton *radioButton = new wxRadioButton(widgetPanel, widgetID, valueWxString, wxDefaultPosition, wxDefaultSize);
4558 theWxContainer = theWxWidget = radioButton;
4559 this->AddToDesiredEvents(wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler(gdlwxFrame::OnRadioButton), radioButton);
4560 buttonType = RADIO;
4561 } else if (gdlParent->GetExclusiveMode() == BGNONEXCLUSIVE) {
4562 wxCheckBox *checkBox = new wxCheckBox(widgetPanel, widgetID, valueWxString, wxDefaultPosition, wxDefaultSize);
4563 theWxContainer = theWxWidget = checkBox;
4564 this->AddToDesiredEvents(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(gdlwxFrame::OnCheckBox), checkBox);
4565 buttonType = CHECKBOX;
4566 } else cerr << "Warning GDLWidgetNormalButton::GDLWidgetNormalButton(): widget type confusion(2)\n";
4567 wxWindow *win = static_cast<wxWindow*> (theWxWidget);
4568 if (win && buttonToolTip) win->SetToolTip(wxString((*buttonToolTip)[0].c_str(), wxConvUTF8));
4569
4570 END_ADD_EVENTUAL_FRAME
4571
4572 win->SetSize(wSize);
4573 win->SetMinSize(wSize);
4574
4575 TIDY_WIDGET(gdlBORDER_SPACE)
4576 // UPDATE_WINDOW
4577 REALIZE_IF_NEEDED
4578
4579
4580 }
4581
SetButtonWidgetLabelText(const DString & value_)4582 void GDLWidgetNormalButton::SetButtonWidgetLabelText(const DString& value_) {
4583 if (theWxWidget != NULL) {
4584 wxAnyButton *b = dynamic_cast<wxAnyButton*> (theWxWidget);
4585 b->SetLabelText(wxString(value_.c_str(), wxConvUTF8));
4586 // Should switch to version > 2.9 now!
4587 #if wxCHECK_VERSION(2,9,1)
4588 b->SetBitmap(wxBitmap(1, 1));
4589 #endif
4590 if (this->IsDynamicResize()) {
4591 this->SetWidgetSize(0,0);
4592 // this->RefreshDynamicWidget();
4593 }
4594 }
4595 }
4596
~GDLWidgetNormalButton()4597 GDLWidgetNormalButton::~GDLWidgetNormalButton() {
4598 #ifdef GDL_DEBUG_WIDGETS
4599 std::cout << "~GDLWidgetNormalButton(" << widgetID << ")" << std::endl;
4600 #endif
4601 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
4602 }
4603
4604 //this type of buttons use a container
GDLWidgetMenu(WidgetIDT p,EnvT * e,DStringGDL * value,DULong eventflags,wxBitmap * bitmap_)4605 GDLWidgetMenu::GDLWidgetMenu(WidgetIDT p, EnvT* e,
4606 DStringGDL* value, DULong eventflags, wxBitmap* bitmap_)
4607 : GDLWidgetButton(p, e, value, eventflags, bitmap_)
4608 {
4609 }
4610
~GDLWidgetMenu()4611 GDLWidgetMenu::~GDLWidgetMenu() {
4612 #ifdef GDL_DEBUG_WIDGETS
4613 std::cout << "~GDLWidgetMenu(" << widgetID << ")" << std::endl;
4614 #endif
4615 // delete all children (in reverse order ?)
4616 while (!children.empty()) {
4617 GDLWidget* child = GetWidget(children.back());
4618 children.pop_back();
4619 if (child) {
4620 #ifdef GDL_DEBUG_WIDGETS
4621 std::cout << "~GDLWidgetMenu(" << widgetID << "): removing child: ID=" << child->GetWidgetID() << std::endl;
4622 #endif
4623 delete child;
4624 } else {
4625 #ifdef GDL_DEBUG_WIDGETS
4626 std::cout << "~GDLWidgetMenu(" << widgetID << "): ignoring unexisting child: ID=" << child->GetWidgetID() << std::endl;
4627 #endif
4628 }
4629 }
4630 }
4631
4632 //this type of buttons use a container
GDLWidgetSubMenu(WidgetIDT p,EnvT * e,DStringGDL * value,DULong eventflags,bool hasSeparatorAbove,wxBitmap * bitmap_)4633 GDLWidgetSubMenu::GDLWidgetSubMenu(WidgetIDT p, EnvT* e,
4634 DStringGDL* value, DULong eventflags, bool hasSeparatorAbove, wxBitmap* bitmap_)
4635 : GDLWidgetMenu(p, e, value, eventflags, bitmap_)
4636 , addSeparatorAbove( hasSeparatorAbove)
4637 , the_sep(NULL)
4638 {
4639 GDLWidget* gdlParent = GetWidget(parentID);
4640
4641 //get default value: a menu. May be NULL here
4642 wxMenu *menu = dynamic_cast<wxMenu*> (gdlParent->GetWxWidget());
4643 wxMenu* submenu = new wxMenu();
4644 if (addSeparatorAbove) the_sep=menu->AppendSeparator();
4645 menuItem = new wxMenuItem(menu, widgetID, valueWxString, wxEmptyString, wxITEM_NORMAL, submenu );
4646 if (bitmap_) menuItem->SetBitmap(*bitmap_);
4647 menu->Append(menuItem);
4648 menu->Enable(menuItem->GetId(), sensitive);
4649 theWxContainer = menu; //is not a window: special treatment
4650 theWxWidget = submenu;
4651 buttonType = MENU;
4652 //No UPDATE_WINDOW see menu entry.
4653
4654 }
4655
SetSensitive(bool value)4656 void GDLWidgetSubMenu::SetSensitive(bool value) {
4657 sensitive = value;
4658 if (menuItem) menuItem->Enable(value);
4659 }
4660
SetButtonWidgetLabelText(const DString & value_)4661 void GDLWidgetSubMenu::SetButtonWidgetLabelText( const DString& value_ ) {
4662 if (menuItem && value_.length() > 0 ) menuItem->SetItemLabel( wxString(value_.c_str( ), wxConvUTF8 ) ); //avoid null strings asserts!
4663 }
4664
SetButtonWidgetBitmap(wxBitmap * bitmap_)4665 void GDLWidgetSubMenu::SetButtonWidgetBitmap( wxBitmap* bitmap_ ) {
4666 if ( menuItem ) {
4667 menuItem->SetBitmap( *bitmap_ ); //probably only MsW
4668 }
4669 }
4670
~GDLWidgetSubMenu()4671 GDLWidgetSubMenu::~GDLWidgetSubMenu() {
4672 #ifdef GDL_DEBUG_WIDGETS
4673 std::cout << "~GDLWidgetSubMenu(" << widgetID << ")" << std::endl;
4674 #endif
4675 GDLWidgetMenu* gdlParent = dynamic_cast<GDLWidgetMenu*> (GetWidget(parentID));
4676 if (gdlParent) gdlParent->RemoveChild(widgetID);
4677
4678 if (menuItem) {
4679 #ifdef GDL_DEBUG_WIDGETS
4680 std::cout << "~GDLWidgetSubMenu(" << widgetID << "): attempting to remove submenu #" << menuItem->GetId() << " from menu " << parentID << std::endl;
4681 #endif
4682 wxMenu* menu = dynamic_cast<wxMenu*> (theWxContainer);
4683 menu->Remove(menuItem);
4684 if (addSeparatorAbove) menu->Remove(the_sep);
4685 }
4686 }
4687
4688 //this type of buttons use a container
GDLWidgetMenuEntry(WidgetIDT p,EnvT * e,DStringGDL * value,DULong eventflags,bool hasSeparatorAbove,wxBitmap * bitmap_,bool checked_type)4689 GDLWidgetMenuEntry::GDLWidgetMenuEntry(WidgetIDT p, EnvT* e,
4690 DStringGDL* value, DULong eventflags, bool hasSeparatorAbove, wxBitmap* bitmap_, bool checked_type)
4691 : GDLWidgetButton(p, e, value, eventflags, bitmap_)
4692 , addSeparatorAbove( hasSeparatorAbove)
4693 , checkedState(false) //unchecked at start
4694 , the_sep(NULL)
4695 {
4696 GDLWidget* gdlParent = GetWidget(parentID);
4697 if (bitmap_) checked_type=false; //wxWidgets does not like checked bitmaps
4698 //get default value: a menu. May be NULL here
4699 wxMenu *menu = dynamic_cast<wxMenu*> (gdlParent->GetWxWidget());
4700 if (addSeparatorAbove) the_sep=menu->AppendSeparator();
4701 menuItem = new wxMenuItem(menu, widgetID, valueWxString,wxEmptyString, checked_type?wxITEM_CHECK:wxITEM_NORMAL);
4702 if (bitmap_) menuItem->SetBitmap(*bitmap_);
4703 menu->Append(menuItem);
4704 menu->Enable(menuItem->GetId(), sensitive);
4705 theWxContainer = menu; //is not a window
4706 theWxWidget = menuItem;
4707 buttonType = ENTRY;
4708 //NO UPDATE WINDOW as menu are dynamical on stack.
4709 }
4710
SetSensitive(bool value)4711 void GDLWidgetMenuEntry::SetSensitive(bool value) {
4712 sensitive = value;
4713 wxMenuItem* item = dynamic_cast<wxMenuItem*> (theWxWidget);
4714 if (item) item->Enable(value);
4715 }
4716
SetButtonWidgetLabelText(const DString & value_)4717 void GDLWidgetMenuEntry::SetButtonWidgetLabelText( const DString& value_ ) {
4718 wxMenuItem* item = dynamic_cast<wxMenuItem*> (theWxWidget);
4719 if (item) item->SetItemLabel(wxString( value_.c_str( ), wxConvUTF8 ));
4720 }
SetButtonWidgetBitmap(wxBitmap * bitmap_)4721 void GDLWidgetMenuEntry::SetButtonWidgetBitmap( wxBitmap* bitmap_ ) {
4722 wxMenuItem* item = dynamic_cast<wxMenuItem*> (theWxWidget);
4723 if (item) {
4724 item->SetBitmap( *bitmap_); //probably only on MSW
4725 }
4726 }
4727
~GDLWidgetMenuEntry()4728 GDLWidgetMenuEntry::~GDLWidgetMenuEntry() {
4729 #ifdef GDL_DEBUG_WIDGETS
4730 std::cout << "~GDLWidgetMenuEntry(" << widgetID << ")" << std::endl;
4731 #endif
4732 GDLWidgetMenu* gdlParent = dynamic_cast<GDLWidgetMenu*>(GetWidget(parentID));
4733 if (gdlParent) gdlParent->RemoveChild(widgetID);
4734 if (menuItem) {
4735 #ifdef GDL_DEBUG_WIDGETS
4736 std::cout << "~GDLWidgetMenuEntry(" << widgetID << "): attempting to remove menuitem #" << menuItem->GetId() << " of menu " << parentID << std::endl;
4737 #endif
4738 wxMenu* menu = dynamic_cast<wxMenu*> (theWxContainer);
4739 menu->Remove(menuItem);
4740 if (addSeparatorAbove) menu->Remove(the_sep);
4741 }
4742 }
4743
4744 //Mbar buttons are pulldown MENUS, so container
4745
4746 #ifdef PREFERS_MENUBAR
GDLWidgetMenuBarButton(WidgetIDT p,EnvT * e,DStringGDL * value,DULong eventflags,DStringGDL * buttonToolTip)4747 GDLWidgetMenuBarButton::GDLWidgetMenuBarButton(WidgetIDT p, EnvT* e,
4748 DStringGDL* value, DULong eventflags, DStringGDL* buttonToolTip)
4749 : GDLWidgetMenu(p, e, value, eventflags, NULL)
4750 , entry(-1) {
4751 GDLWidgetMenuBar* gdlParent = dynamic_cast<GDLWidgetMenuBar*> (GetWidget(parentID));
4752 if (gdlParent) {
4753 wxMenuBar *menuBar = dynamic_cast<wxMenuBar*> (gdlParent->GetWxWidget());
4754 assert(menuBar != NULL);
4755 wxMenu* menu = new wxMenu();
4756 theWxContainer = menuBar; //not a WwxWindow
4757 theWxWidget = menu;
4758 entry = menuBar->GetMenuCount();
4759 menuBar->Insert(entry, menu, valueWxString);
4760 menuBar->EnableTop(entry, sensitive);
4761 buttonType = MENU;
4762
4763 //MBAR menus cannot have a tooltip due to
4764
4765 // UPDATE_WINDOW; REALIZE_IF_NEEDED; //made on the fly, non need.
4766 }
4767 }
4768
4769 #else
GDLWidgetMenuBarButton(WidgetIDT p,EnvT * e,DStringGDL * value,DULong eventflags,wxBitmap * bitmap_,DStringGDL * buttonToolTip)4770 GDLWidgetMenuBarButton::GDLWidgetMenuBarButton(WidgetIDT p, EnvT* e,
4771 DStringGDL* value, DULong eventflags, wxBitmap* bitmap_, DStringGDL* buttonToolTip)
4772 : GDLWidgetMenu(p, e, value, eventflags, NULL)
4773 , entry(NULL) {
4774
4775
4776 GDLWidgetMenuBar* gdlParent = dynamic_cast<GDLWidgetMenuBar*> (GetWidget(parentID));
4777 assert(gdlParent->IsMenuBar());
4778
4779 wxToolBar *toolBar = dynamic_cast<wxToolBar*> (gdlParent->GetWxWidget());
4780 assert(toolBar != NULL);
4781 if (bitmap_ == NULL) {
4782 wSize=computeWidgetSize();
4783 wxButtonGDL *button = new wxButtonGDL(font, toolBar, widgetID, valueWxString,
4784 wOffset, wSize, wxBORDER_NONE);
4785 buttonType = POPUP_NORMAL; //gdlMenuButton is a wxButton --> normal. Bitmaps will be supported starting from 2.9.1
4786 theWxContainer = button;
4787 theWxWidget = button->GetPopupMenu(); //a menu
4788 button->Enable(sensitive);
4789 entry=toolBar->AddControl(button);
4790 wxSize tbSize=toolBar->GetSize();
4791 if (tbSize.y < wSize.y) toolBar->SetSize(wxSize(-1,wSize.y));
4792 toolBar->Realize();
4793 } else {
4794 wxBitmapButtonGDL *button = new wxBitmapButtonGDL(toolBar, widgetID, *bitmap_,
4795 wOffset, wSize, wxBU_EXACTFIT|wxBORDER_NONE);
4796 buttonType = POPUP_BITMAP; //
4797 theWxContainer = button;
4798 theWxWidget = button->GetPopupMenu(); //a menu
4799 button->Enable(sensitive);
4800 entry=toolBar->AddControl(button);
4801 wxSize tbSize=toolBar->GetSize();
4802 if (tbSize.y < wSize.y) toolBar->SetSize(wxSize(-1,wSize.y));
4803 toolBar->Realize();
4804 }
4805
4806 wxWindow *win = dynamic_cast<wxWindow*> (theWxContainer);
4807 if (win) {
4808 if (buttonToolTip) win->SetToolTip(wxString((*buttonToolTip)[0].c_str(), wxConvUTF8));
4809 if (widgetSizer) widgetSizer->Add(win, DONOTALLOWSTRETCH, widgetStyle|wxALL, gdlSPACE); //|wxALL, gdlSPACE_BUTTON);
4810 } else cerr << "Warning GDLWidgetMenuButton::GDLWidgetMenuButton(): widget type confusion.\n";
4811
4812 // UPDATE_WINDOW; REALIZE_IF_NEEDED;
4813 }
4814 #endif
4815
SetSensitive(bool value)4816 void GDLWidgetMenuBarButton::SetSensitive(bool value) {
4817 #ifdef PREFERS_MENUBAR
4818 sensitive = value;
4819 wxMenuBar *menuBar = dynamic_cast<wxMenuBar*> (theWxContainer);
4820 menuBar->EnableTop(entry, value);
4821 #else
4822 GDLWidget::SetSensitive(value) ;
4823 #endif
4824 }
4825
SetButtonWidgetLabelText(const DString & value_)4826 void GDLWidgetMenuBarButton::SetButtonWidgetLabelText( const DString& value_ ) {
4827 #ifdef PREFERS_MENUBAR
4828 wxMenuBar *menuBar = dynamic_cast<wxMenuBar*> (theWxContainer);
4829 menuBar->SetMenuLabel(entry, wxString( value_.c_str( ), wxConvUTF8 ));
4830 #else
4831 wxButton* m=dynamic_cast<wxButton*>(theWxWidget);
4832 if (m) m->SetLabelText(wxString( value_.c_str( ), wxConvUTF8 ));
4833 this->RefreshDynamicWidget();
4834 #endif
4835 }
4836
~GDLWidgetMenuBarButton()4837 GDLWidgetMenuBarButton::~GDLWidgetMenuBarButton() {
4838 #ifdef GDL_DEBUG_WIDGETS
4839 std::cout << "~GDLWidgetMenuBarButton(" << widgetID << ")" << std::endl;
4840 #endif
4841 #ifdef PREFERS_MENUBAR
4842 GDLWidgetMenuBar* gdlParent = dynamic_cast<GDLWidgetMenuBar*>(GetWidget(parentID));
4843 //which pos?
4844 if (gdlParent) {
4845 int pos=gdlParent->GetChildrenPos(widgetID);
4846 gdlParent->RemoveChild(widgetID);
4847 if (pos >= 0) {
4848 wxMenuBar *menuBar = dynamic_cast<wxMenuBar*> (theWxContainer);
4849 menuBar->Remove(pos);
4850 }
4851 }
4852 #else
4853 GDLWidgetMenuBar* gdlParent = dynamic_cast<GDLWidgetMenuBar*> (GetWidget(parentID));
4854 assert(gdlParent->IsMenuBar());
4855 wxToolBar *toolBar = dynamic_cast<wxToolBar*> (gdlParent->GetWxWidget());
4856 assert(toolBar != NULL);
4857 toolBar->RemoveTool(widgetID);
4858 #endif
4859 }
4860
4861 //a MenuButton Widget is an otherwise normal button in a Base that activates a pulldown menu and is a container
GDLWidgetMenuButton(WidgetIDT p,EnvT * e,DStringGDL * value,DULong eventflags,wxBitmap * bitmap_,DStringGDL * buttonToolTip)4862 GDLWidgetMenuButton::GDLWidgetMenuButton(WidgetIDT p, EnvT* e,
4863 DStringGDL* value, DULong eventflags, wxBitmap* bitmap_, DStringGDL* buttonToolTip)
4864 : GDLWidgetMenu(p, e, value, eventflags, bitmap_) {
4865 GDLWidget* gdlParent = GetWidget(parentID);
4866 widgetPanel = GetParentPanel();
4867 widgetSizer = GetParentSizer();
4868 widgetStyle = widgetAlignment();
4869 wSize = computeWidgetSize();
4870
4871 assert(gdlParent->IsBase());
4872
4873 //A menu button in a base is a button starting a popup menu. it is a container also.
4874 //2 different buttons, if bitmap or not, waiting for version > 2.9.1 to have bitmaps handled for ALL buttontypes:
4875 if (bitmap_ == NULL) {
4876 wxButtonGDL *button = new wxButtonGDL(font, widgetPanel, widgetID, valueWxString,
4877 wOffset, wxDefaultSize, buttonTextAlignment());
4878 button->SetSize(wSize);
4879 button->SetMinSize(wSize);
4880 buttonType = POPUP_NORMAL; //gdlMenuButton is a wxButton --> normal. Bitmaps will be supported starting from 2.9.1
4881 theWxContainer = button;
4882 theWxWidget = button->GetPopupMenu(); //a menu
4883 button->Enable(sensitive);
4884 } else {
4885 wxBitmapButtonGDL *button = new wxBitmapButtonGDL(widgetPanel, widgetID, *bitmap_,
4886 wOffset, wxDefaultSize, buttonTextAlignment());
4887 button->SetSize(wSize);
4888 button->SetMinSize(wSize);
4889 buttonType = POPUP_BITMAP; //
4890 theWxContainer = button;
4891 theWxWidget = button->GetPopupMenu(); //a menu
4892 button->Enable(sensitive);
4893 }
4894 wxWindow *win = dynamic_cast<wxWindow*> (theWxContainer);
4895 if (win) {
4896 if (buttonToolTip) win->SetToolTip(wxString((*buttonToolTip)[0].c_str(), wxConvUTF8));
4897 if (widgetSizer) widgetSizer->Add(win, DONOTALLOWSTRETCH, widgetStyle|wxALL, gdlSPACE); //|wxALL, gdlSPACE_BUTTON);
4898 } else cerr << "Warning GDLWidgetMenuButton::GDLWidgetMenuButton(): widget type confusion.\n";
4899
4900 // UPDATE_WINDOW
4901 REALIZE_IF_NEEDED
4902 }
4903
SetSensitive(bool value)4904 void GDLWidgetMenuButton::SetSensitive(bool value) {
4905 sensitive = value;
4906 wxButton* m = dynamic_cast<wxButton*> (theWxContainer);
4907 if (m) m->Enable(value);
4908 }
4909
SetButtonWidgetLabelText(const DString & value_)4910 void GDLWidgetMenuButton::SetButtonWidgetLabelText( const DString& value_ ) {
4911 wxButton* m=dynamic_cast<wxButton*>(theWxContainer);
4912 if (m) m->SetLabelText(wxString( value_.c_str( ), wxConvUTF8 ));
4913 this->RefreshDynamicWidget();
4914 }
4915
~GDLWidgetMenuButton()4916 GDLWidgetMenuButton::~GDLWidgetMenuButton() {
4917 #ifdef GDL_DEBUG_WIDGETS
4918 std::cout << "~GDLWidgetMenuButton(" << widgetID << ")" << std::endl;
4919 #endif
4920 GDLWidgetBase* b=dynamic_cast<GDLWidgetBase*>(GetWidget(parentID));
4921 if (b && !b->IsContextBase()) if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
4922 }
4923
SetButtonWidgetBitmap(wxBitmap * bitmap_)4924 void GDLWidgetButton::SetButtonWidgetBitmap( wxBitmap* bitmap_ ) {
4925 if ( buttonType == BITMAP) {
4926 wxBitmapButton *b = dynamic_cast<wxBitmapButton*> (theWxWidget);
4927 if ( b ) {
4928 b->SetBitmapLabel( *bitmap_ );
4929 b->SetLabelText(wxEmptyString);
4930 }
4931 } else if ( buttonType == POPUP_BITMAP ) {
4932 wxBitmapButton *b = dynamic_cast<wxBitmapButton*> (theWxContainer); //not the wxWidget since the widget is the popup menu itself.
4933 if ( b ) {
4934 b->SetBitmapLabel( *bitmap_ );
4935 b->SetLabelText(wxEmptyString);
4936 }
4937 } else if ( buttonType == MENU || buttonType ==ENTRY) {
4938 if ( menuItem != NULL ) {
4939 menuItem->SetBitmap( *bitmap_ );
4940 menuItem->SetItemLabel(wxT(" ")); //setting null strings to menus is not permitted !!!!
4941 }
4942 }
4943 // Should switch to version > 2.9 now!
4944 #if wxCHECK_VERSION(2,9,1)
4945 else if ( buttonType == NORMAL || buttonType == POPUP_NORMAL) {
4946 wxButton *b = dynamic_cast<wxButton*> (theWxWidget);
4947 if ( b ) {
4948 b->SetBitmapLabel( *bitmap_ );
4949 b->SetLabelText(wxEmptyString);
4950 }
4951 }
4952 #endif
4953 this->RefreshDynamicWidget();
4954 }
4955
GDLWidgetList(WidgetIDT p,EnvT * e,BaseGDL * value,DLong style,DULong eventflags)4956 GDLWidgetList::GDLWidgetList( WidgetIDT p, EnvT* e, BaseGDL *value, DLong style, DULong eventflags )
4957 : GDLWidget( p, e, value, eventflags)
4958 , maxlinelength(0)
4959 , nlines(0)
4960 {
4961 GDLWidget* gdlParent = GetWidget( parentID );
4962 widgetPanel = GetParentPanel( );
4963 widgetSizer = GetParentSizer( );
4964
4965 START_ADD_EVENTUAL_FRAME
4966
4967 widgetStyle = widgetAlignment();
4968 if( vValue->Type() != GDL_STRING)
4969 {
4970 vValue = static_cast<DStringGDL*> (vValue->Convert2( GDL_STRING, BaseGDL::CONVERT ));
4971 }
4972 DStringGDL* val = static_cast<DStringGDL*> (vValue);
4973
4974 nlines = val->N_Elements( );
4975 wxArrayString choices; // = new wxString[n];
4976 for ( SizeT i = 0; i < nlines; ++i ){
4977 int length=(*val)[i].length();
4978 if (length>maxlinelength){
4979 maxlinelength=length;
4980 }
4981 choices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) );
4982 }
4983 wxListBox * list=new wxListBox();
4984 theWxContainer = theWxWidget = list;
4985 //ok now size can be computed
4986 list->Create(widgetPanel, widgetID, wxDefaultPosition, wxDefaultSize , choices, style|wxLB_NEEDED_SB|wxLB_SINGLE); //|wxLB_MULTIPLE );
4987 this->setFont(); //set fancy font before computing sizes!
4988 wSize=computeWidgetSize();
4989 list->SetClientSize(wSize);
4990 list->SetMinClientSize(wSize);
4991 list->SetSelection(wxNOT_FOUND);//necessary to avoid spurious event on first click.
4992 this->AddToDesiredEvents( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED,wxCommandEventHandler(gdlwxFrame::OnListBoxDoubleClicked),list);
4993 this->AddToDesiredEvents( wxEVT_COMMAND_LISTBOX_SELECTED,wxCommandEventHandler(gdlwxFrame::OnListBox),list);
4994
4995 END_ADD_EVENTUAL_FRAME
4996 TIDY_WIDGET(gdlBORDER_SPACE)
4997
4998 // UPDATE_WINDOW
4999 REALIZE_IF_NEEDED
5000 }
SetWidgetSize(DLong sizex,DLong sizey)5001 void GDLWidgetList::SetWidgetSize(DLong sizex, DLong sizey)
5002 {
5003
5004 START_CHANGESIZE_NOEVENT
5005
5006 wxWindow* me = dynamic_cast<wxWindow*> (this->GetWxWidget());
5007 if (me == NULL) {
5008 #ifdef GDL_DEBUG_WIDGETS
5009 wxMessageOutputStderr().Printf(_T("GDLWidgetList::SetSize of non wxWindow %s\n"), this->GetWidgetName().c_str());
5010 #endif
5011 return;
5012 }
5013 //a graphic window cannot be larger than the base widget it is in, if the base widget size has been fixed
5014 wxSize currentSize=me->GetSize();
5015 wxSize currentBestSize=me->GetBestSize();
5016 #ifdef GDL_DEBUG_WIDGETS
5017 wxMessageOutputStderr( ).Printf( _T( "GDLWidgetList::SetSize currentSize=%d,%d \n"),currentSize.x,currentSize.y);
5018 #endif
5019
5020 //widget text size is in LINES in Y and CHARACTERS in X.
5021 wxRealPoint widgetSize = wxRealPoint(-1,-1);
5022 wxSize fontSize = getFontSize();
5023 //based on experience, actual line height is 1.2 times font y size for fonts > 20 but 1.5 for smaller fonts
5024 int lineHeight=(fontSize.y<20)?fontSize.y*1.5:fontSize.y*1.2;
5025 if (sizex > 0) {
5026 widgetSize.x = (sizex+0.5) * fontSize.x;
5027 } else {
5028 widgetSize.x = currentSize.x;
5029 }
5030
5031 if (sizey > 0) {
5032 widgetSize.y =sizey * lineHeight;
5033 } else {
5034 widgetSize.y = currentSize.y;
5035 }
5036
5037 if (sizex > 0 && maxlinelength > sizex) widgetSize.y += gdlSCROLL_HEIGHT_X;
5038 if (nlines > sizey) widgetSize.x += gdlSCROLL_WIDTH_Y;
5039 widgetSize.y += 10;
5040
5041 sizex=ceil(widgetSize.x);
5042 sizey=ceil(widgetSize.y);
5043 wSize.x = sizex;
5044 wSize.y = sizey;
5045 me->SetSize(wSize);
5046 me->SetMinSize(wSize);
5047
5048 if (!widgetSizer) { if (framePanel) framePanel->Fit();}
5049
5050 UPDATE_WINDOW
5051
5052 END_CHANGESIZE_NOEVENT
5053
5054 #ifdef GDL_DEBUG_WIDGETS
5055 wxMessageOutputStderr().Printf(_T("GDLWidgetList::SetSize %d,%d (%s)\n"), sizex, sizey, this->GetWidgetName().c_str());
5056 #endif
5057 }
5058
SetValue(BaseGDL * value)5059 void GDLWidgetList::SetValue(BaseGDL *value){
5060 GDLDelete(vValue);
5061 vValue=value;
5062 if( vValue->Type() != GDL_STRING)
5063 {
5064 vValue = static_cast<DStringGDL*> (vValue->Convert2( GDL_STRING, BaseGDL::CONVERT ));
5065 }
5066 DStringGDL* val = static_cast<DStringGDL*> (vValue);
5067
5068 wxArrayString newchoices; // = new wxString[n];
5069 nlines = val->N_Elements( );
5070 for ( SizeT i = 0; i < nlines; ++i ){
5071 int length=(*val)[i].length();
5072 if (length>maxlinelength){
5073 maxlinelength=length;
5074 }
5075 newchoices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) );
5076 }
5077
5078 wxListBox * list = dynamic_cast<wxListBox*>(theWxWidget);
5079 assert( list != NULL);
5080
5081 list->Clear();
5082 list->InsertItems(newchoices,0);
5083 list->SetSelection(wxNOT_FOUND);
5084 }
5085
SelectEntry(DLong entry_number)5086 void GDLWidgetList::SelectEntry(DLong entry_number){
5087 if (entry_number < 0 ) return;
5088 wxListBox * list=dynamic_cast<wxListBox*>(theWxWidget);
5089 assert( list != NULL);
5090 if (entry_number > list->GetCount()-1) return;
5091 list->Select(entry_number);
5092 }
5093
GetSelectedEntries()5094 BaseGDL* GDLWidgetList::GetSelectedEntries(){
5095 wxListBox * list=dynamic_cast<wxListBox*>(theWxWidget);
5096 assert( list != NULL);
5097 wxArrayInt selections;
5098 list->GetSelections(selections);
5099 DIntGDL* liste;
5100 if (selections.Count()<1) {
5101 liste=new DIntGDL(-1);
5102 return liste;
5103 }
5104 liste=new DIntGDL(dimension(selections.Count()));
5105 for (SizeT i=0; i< selections.Count(); ++i) (*liste)[i]=selections[i];
5106 return liste;
5107 }
5108
~GDLWidgetList()5109 GDLWidgetList::~GDLWidgetList(){
5110 #ifdef GDL_DEBUG_WIDGETS
5111 std::cout << "~GDLWidgetList(" << widgetID << ")" << std::endl;
5112 #endif
5113 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
5114 }
5115
GDLWidgetDropList(WidgetIDT p,EnvT * e,BaseGDL * value,DULong eventflags,const DString & title_,DLong style_)5116 GDLWidgetDropList::GDLWidgetDropList( WidgetIDT p, EnvT* e, BaseGDL *value, DULong eventflags ,
5117 const DString& title_, DLong style_ )
5118 : GDLWidget( p, e, static_cast<DStringGDL*> (value->Convert2( GDL_STRING, BaseGDL::CONVERT )), eventflags)
5119 , title( title_ )
5120 , style( style_)
5121 {
5122 GDLWidget* gdlParent = GetWidget(parentID);
5123 widgetPanel = GetParentPanel();
5124 widgetSizer = GetParentSizer();
5125
5126 DStringGDL* val = static_cast<DStringGDL*> (vValue);
5127 DLong n = val->N_Elements();
5128 wxArrayString choices; // = new wxString[n];
5129 for (SizeT i = 0; i < n; ++i) {
5130 choices.Add(wxString((*val)[i].c_str(), wxConvUTF8));
5131 }
5132
5133 /// static int flatIx=e->KeywordIx("FLAT"); ignored.
5134 widgetStyle=widgetAlignment();
5135 bool hastitle=(title.size()>0);
5136
5137 //get defined sizes if any
5138 wSize=computeWidgetSize( );
5139
5140 wxChoice * droplist;
5141 theWxContainer=NULL;
5142 wxSizer* theSizer=NULL;
5143 wxWindow* theWindow = widgetPanel;
5144 if (frameWidth > 0) {
5145 framePanel=new wxPanel(theWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, gdlBORDER_EXT);
5146 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
5147 framePanel->SetBackgroundColour(wxColour(0x3a, 0x82, 0x56)); //vert fonce
5148 #endif
5149 wxSizer* frameSizer=new wxBoxSizer(wxVERTICAL);
5150 framePanel->SetSizer(frameSizer);
5151 theWxContainer=framePanel;
5152 theWindow=framePanel;
5153 wxPanel* intFramePanel=new wxPanel(framePanel);
5154 theWindow=intFramePanel;
5155 frameSizer->Add(intFramePanel, DONOTALLOWSTRETCH, wxALL, frameWidth);
5156 }
5157 if (hastitle) {
5158 wxPanel* comboPanel=new wxPanel(theWindow, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE);
5159 wxSizer* combosz = new wxBoxSizer(wxHORIZONTAL);
5160 comboPanel->SetSizer(combosz);
5161 if (!theWxContainer) theWxContainer = comboPanel; //else stays as panel_if_framed.
5162 this->setFont(comboPanel); //enable fancy font
5163 wxStaticText *theTitle=new wxStaticText(comboPanel,wxID_ANY,wxString(title.c_str(), wxConvUTF8));
5164 combosz->Add(theTitle,DONOTALLOWSTRETCH, wxALIGN_CENTER|wxALL,gdlSPACE);
5165 combosz->AddSpacer(5);
5166 droplist = new wxChoice( comboPanel, widgetID, wxDefaultPosition, wxDefaultSize, choices, style );
5167 droplist->SetSize(wSize);
5168 droplist->SetMinSize(wSize);
5169 theWxWidget = droplist;
5170 combosz->Add(droplist,DONOTALLOWSTRETCH,wxALIGN_CENTER|wxALL,gdlSPACE);
5171 combosz->Fit(droplist);
5172 comboPanel->Fit();
5173 } else {
5174 droplist = new wxChoice( theWindow, widgetID, wxDefaultPosition, wxDefaultSize, choices, style );
5175 droplist->SetSize(wSize);
5176 droplist->SetMinSize(wSize);
5177 theWxWidget = droplist;
5178 if (!theWxContainer) theWxContainer = droplist;
5179 }
5180 if (framePanel) framePanel->Fit();
5181 if (widgetSizer) {
5182 widgetSizer->Add(dynamic_cast<wxWindow*>(theWxContainer), DONOTALLOWSTRETCH, widgetStyle|wxALL, gdlTEXT_SPACE);
5183 widgetSizer->Fit(dynamic_cast<wxWindow*>(theWxContainer));
5184 } else {
5185 widgetPanel->Fit();
5186 dynamic_cast<wxWindow*>(theWxContainer)->SetPosition(wOffset);
5187 }
5188
5189
5190 droplist->SetSelection(0);
5191 this->AddToDesiredEvents( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler(gdlwxFrame::OnDropList),droplist);
5192
5193 // UPDATE_WINDOW
5194 REALIZE_IF_NEEDED
5195 }
5196
SetValue(BaseGDL * value)5197 void GDLWidgetDropList::SetValue(BaseGDL *value){
5198 GDLDelete(vValue);
5199 vValue=value;
5200 if( vValue->Type() != GDL_STRING)
5201 {
5202 vValue = static_cast<DStringGDL*> (vValue->Convert2( GDL_STRING, BaseGDL::CONVERT ));
5203 }
5204 DStringGDL* val = static_cast<DStringGDL*> (vValue);
5205 wxArrayString newchoices; // = new wxString[n];
5206 for ( SizeT i = 0; i < val->N_Elements( ); ++i ) newchoices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) );
5207
5208 wxChoice* droplist=dynamic_cast<wxChoice*>(theWxWidget);
5209 assert( droplist != NULL);
5210 droplist->Clear();
5211 droplist->Append(newchoices);
5212 droplist->SetSelection(0);
5213 //IDL behaviour with DynamicResize is identical
5214 if (this->IsDynamicResize()) {
5215 wSize=droplist->GetSizeFromTextSize(droplist->GetTextExtent(newchoices[0]).GetWidth());
5216 droplist->SetMinSize(wSize);
5217 droplist->SetSize(wSize);
5218 }
5219 RefreshDynamicWidget();
5220 }
5221
SelectEntry(DLong entry_number)5222 void GDLWidgetDropList::SelectEntry(DLong entry_number){
5223 wxChoice * droplist=dynamic_cast<wxChoice*>(theWxWidget);
5224 assert( droplist != NULL);
5225 droplist->Select(entry_number);
5226 }
5227
GetSelectedEntry()5228 BaseGDL* GDLWidgetDropList::GetSelectedEntry(){
5229 wxChoice * droplist=dynamic_cast<wxChoice*>(theWxWidget);
5230 assert( droplist != NULL);
5231 return new DIntGDL(droplist->GetSelection());
5232 }
5233
~GDLWidgetDropList()5234 GDLWidgetDropList::~GDLWidgetDropList(){
5235 #ifdef GDL_DEBUG_WIDGETS
5236 std::cout << "~GDLWidgetDropList(" << widgetID << ")" << std::endl;
5237 #endif
5238 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
5239 }
5240
GDLWidgetComboBox(WidgetIDT p,EnvT * e,BaseGDL * value,DULong eventflags,DLong style_)5241 GDLWidgetComboBox::GDLWidgetComboBox( WidgetIDT p, EnvT* e, BaseGDL *value, DULong eventflags, DLong style_ )
5242 : GDLWidget( p, e, static_cast<DStringGDL*> (value->Convert2( GDL_STRING, BaseGDL::CONVERT )) , eventflags)
5243 , style( style_)
5244 {
5245 GDLWidget* gdlParent = GetWidget( parentID );
5246 widgetPanel = GetParentPanel( );
5247 widgetSizer = GetParentSizer( );
5248
5249 START_ADD_EVENTUAL_FRAME
5250
5251 widgetStyle=widgetAlignment();
5252 // wxSize size = computeWidgetSize();
5253
5254 DStringGDL* val = static_cast<DStringGDL*> (vValue);
5255 DLong n = val->N_Elements( );
5256 wxArrayString choices; // = new wxString[n];
5257 for ( SizeT i = 0; i < n; ++i )
5258 choices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) );
5259
5260 wxString val0WxString = wxString( (*val)[0].c_str( ), wxConvUTF8 );
5261
5262 wxComboBox * combobox = new wxComboBox();
5263 combobox->Create(widgetPanel, widgetID, val0WxString, wxDefaultPosition, wxDefaultSize, choices, style );
5264
5265
5266 theWxContainer = theWxWidget = combobox;
5267 this->AddToDesiredEvents( wxEVT_COMMAND_COMBOBOX_SELECTED,wxCommandEventHandler(gdlwxFrame::OnComboBox),combobox);
5268 if (style & wxTE_PROCESS_ENTER) this->AddToDesiredEvents( wxEVT_COMMAND_TEXT_ENTER,wxCommandEventHandler(gdlwxFrame::OnComboBoxTextEnter),combobox);
5269 wSize=computeWidgetSize();
5270 if (widgetSizer==NULL) {
5271 if (wSize.x < 1) wSize.x=gdlDEFAULT_XSIZE+gdlCOMBOBOX_ARROW_WIDTH;
5272 }
5273 combobox->SetSize(wSize);
5274 combobox->SetMinSize(wSize);
5275
5276 END_ADD_EVENTUAL_FRAME
5277 TIDY_WIDGET(gdlBORDER_SPACE)
5278 // UPDATE_WINDOW
5279 REALIZE_IF_NEEDED
5280 }
5281
SetValue(BaseGDL * value)5282 void GDLWidgetComboBox::SetValue(BaseGDL *value){
5283 GDLDelete(vValue);
5284 vValue=value;
5285 if( vValue->Type() != GDL_STRING)
5286 {
5287 vValue = static_cast<DStringGDL*> (vValue->Convert2( GDL_STRING, BaseGDL::CONVERT ));
5288 }
5289 DStringGDL* val = static_cast<DStringGDL*> (vValue);
5290 wxArrayString newchoices; // = new wxString[n];
5291 for ( SizeT i = 0; i < val->N_Elements( ); ++i ) newchoices.Add( wxString( (*val)[i].c_str( ), wxConvUTF8 ) );
5292
5293 wxComboBox * combo = dynamic_cast<wxComboBox*>(theWxWidget);
5294 assert( combo != NULL);
5295 combo->Clear();
5296 combo->Append(newchoices);
5297 combo->SetSelection(0,0);
5298 combo->SetValue(newchoices[0]);
5299 //IDL behaviour with DynamicResize is different as Combobox's size never decreases with this method, it cannot be smaller than the initial size.
5300 //this would plead to have a new wInitialSize for which wSize cannot be smaller her, but is reset to new values with SetSize. Oh well.
5301 if (this->IsDynamicResize()) {
5302 wSize=combo->GetSizeFromTextSize(combo->GetTextExtent(newchoices[0]).GetWidth());
5303 combo->SetMinSize(wSize);
5304 combo->SetSize(wSize);
5305 }
5306 RefreshDynamicWidget();
5307 }
5308
AddItem(DString value,DLong pos)5309 void GDLWidgetComboBox::AddItem(DString value, DLong pos) {
5310 wxComboBox * combo = dynamic_cast<wxComboBox*>(theWxWidget);
5311 assert( combo != NULL);
5312 int nvalues=combo->GetCount();
5313 if (pos == -1) combo->Append( wxString( value.c_str( ), wxConvUTF8 ) );
5314 else if (pos > -1 && pos < nvalues) combo->Insert( wxString( value.c_str( ), wxConvUTF8 ), pos);
5315 }
5316
DeleteItem(DLong pos)5317 void GDLWidgetComboBox::DeleteItem(DLong pos) {
5318 wxComboBox * combo = dynamic_cast<wxComboBox*>(theWxWidget);
5319 assert( combo != NULL);
5320 int nvalues=combo->GetCount();
5321 int selected=combo->GetSelection();
5322 if (pos > -1 && pos < nvalues) combo->Delete( pos );
5323 if (pos==selected && (nvalues-1) > 0 ) combo->Select((pos+1)%(nvalues-1)); else if (selected==-1 && pos==0) combo->Select(0);
5324 }
5325
SelectEntry(DLong entry_number)5326 void GDLWidgetComboBox::SelectEntry(DLong entry_number){
5327 wxComboBox * combo=dynamic_cast<wxComboBox*>(theWxWidget);
5328 assert( combo != NULL);
5329 combo->Select(entry_number);
5330 }
5331
GetSelectedEntry()5332 BaseGDL* GDLWidgetComboBox::GetSelectedEntry(){
5333 wxComboBox * combo=dynamic_cast<wxComboBox*>(theWxWidget);
5334 assert( combo != NULL);
5335 DStringGDL* stringres=new DStringGDL(dimension(1));
5336 (*stringres)[0]=combo->GetStringSelection().mb_str(wxConvUTF8); //return null string if no selection
5337 return stringres;
5338 }
5339
~GDLWidgetComboBox()5340 GDLWidgetComboBox::~GDLWidgetComboBox(){
5341 #ifdef GDL_DEBUG_WIDGETS
5342 std::cout << "~GDLWidgetComboBox(" << widgetID <<")"<< std::endl;
5343 #endif
5344 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
5345 }
5346
GDLWidgetText(WidgetIDT p,EnvT * e,DStringGDL * valueStr,DULong eventflags,bool noNewLine_,bool editable_)5347 GDLWidgetText::GDLWidgetText( WidgetIDT p, EnvT* e, DStringGDL* valueStr, DULong eventflags, bool noNewLine_,
5348 bool editable_ )
5349 : GDLWidget( p, e, valueStr, eventflags )
5350 , noNewLine( noNewLine_ )
5351 , editable(editable_)
5352 , multiline(false)
5353 , maxlinelength(0)
5354 {
5355 static int wrapIx=e->KeywordIx("WRAP");
5356 wrapped=(e->KeywordSet(wrapIx));
5357 DString value = "";
5358 nlines=1;
5359 //textSize is the current size (fixed or computed) in characters.
5360 textSize=wSize;
5361 if (textSize.y > 1) multiline=true; //multiline is a property implied by the widget Ysize, nothing else
5362 //reform entries into one string, with eventual \n . If noNewLines, do not insert a \n . If ysize=1 and no scroll, idem.
5363 bool doNotAddNl=(noNewLine || (!multiline) );
5364
5365 if( vValue != NULL)
5366 {
5367 for( int i=0; i<vValue->N_Elements(); ++i)
5368 {
5369 int length=((*static_cast<DStringGDL*> (vValue))[i]).length();
5370 value += (*static_cast<DStringGDL*> (vValue))[i];
5371 if ( !doNotAddNl) maxlinelength=(length>maxlinelength)?length:maxlinelength; else maxlinelength+=length;
5372 if ( !doNotAddNl )
5373 #ifdef _WIN32
5374 {value += "\r\n"; nlines++;}
5375 #else
5376 {value += '\n'; nlines++;}
5377 #endif
5378 }
5379 }
5380
5381 lastValue = value;
5382
5383 //now the string is formatted as the widget will see it. If the string contains \n the widget will be multiline anyway.
5384 //recompute number of \n as some could have been embedded in each of the strings
5385 //recompute nlines, maxlinelength from start to be sure
5386 nlines=1;
5387 maxlinelength=0;
5388 const char* s=lastValue.c_str();
5389 int length=0;
5390 for (int i=0; i<lastValue.length(); ++i, ++length)
5391 {
5392 if (s[i]==10) {
5393 maxlinelength=(length>maxlinelength)?length:maxlinelength;
5394 nlines++;
5395 length=0;
5396 }
5397 }
5398 if (length>maxlinelength) maxlinelength=length; //if no last return.
5399
5400 GDLWidget* gdlParent = GetWidget( parentID );
5401 widgetPanel = GetParentPanel( );
5402 widgetSizer = GetParentSizer( );
5403
5404 START_ADD_EVENTUAL_FRAME
5405
5406 widgetStyle = widgetAlignment();
5407 bool report=((eventFlags & GDLWidget::EV_ALL)==1);
5408
5409 //for text, apparently, if wxTE_MULTILINE is in effect, the font handler is probably RichText
5410 //and the text SIZE is OK only if imposed by a wxTextAttr. (go figure).
5411 //note that computeWidgetSize() above returns sizes "compatible" with the font size, without any trouble.
5412 wxTextAttr attr= wxTextAttr ();
5413 attr.SetFont(font, wxTEXT_ATTR_FONT);
5414 wxString valueWxString = wxString( lastValue.c_str( ), wxConvUTF8 );
5415 long textStyle = wxTE_RICH2|wxTE_NOHIDESEL;
5416
5417 if (multiline) textStyle |= wxTE_MULTILINE;
5418 if (!scrolled) {textStyle |= wxTE_NO_VSCROLL;} else {textStyle |= wxHSCROLL;}
5419 if (wrapped) textStyle |= wxTE_WORDWRAP; else textStyle |= wxTE_DONTWRAP;
5420 if (!editable && !report ) textStyle |= wxTE_READONLY;
5421
5422 wxTextCtrlGDL* text = new wxTextCtrlGDL(widgetPanel, widgetID, wxEmptyString/*valueWxString*/, wxDefaultPosition, wxDefaultSize, textStyle);
5423 // above, permits to a procedure (cw_field.pro for example) to filter the editing of text fields.
5424 // so wxTextCtrl::OnChar is overwritten in gdlwidgeteventhandler.cpp just for this reason.
5425 theWxContainer = theWxWidget = text;
5426 this->setFont();
5427 if ((textStyle & wxTE_MULTILINE)==0) text->SetMargins(wxPoint(gdlTEXT_XMARGIN,gdlTEXT_YMARGIN)); //without the if clause, provokes: GLib-GObject-WARNING **: 23:04:21.080: invalid cast from 'GtkTextView' to 'GtkEntry' (and does not work)
5428 text->SetDefaultStyle(attr);
5429 text->SetValue(valueWxString);
5430
5431 wSize = computeWidgetSize(); //updates textSize.
5432 text->SetClientSize(wSize);
5433 text->SetMinClientSize(wSize);
5434
5435 text->SetSelection(0,0);
5436 text->SetInsertionPoint(0);
5437 text->ShowPosition(0);
5438
5439 END_ADD_EVENTUAL_FRAME
5440 TIDY_WIDGET(gdlBORDER_SPACE)
5441
5442 // this->AddToDesiredEvents( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(GDLFrame::OnTextEnter),text); //NOT USED
5443 if( editable || report) this->AddToDesiredEvents(wxEVT_CHAR, wxKeyEventHandler(wxTextCtrlGDL::OnChar),text);
5444 //add scrolling even if text is not scrollable since scroll is not permitted (IDL widgets are not at all the same as GTK...)
5445 if (!scrolled) this->AddToDesiredEvents(wxEVT_MOUSEWHEEL, wxMouseEventHandler(wxTextCtrlGDL::OnMouseEvents),text);
5446 this->AddToDesiredEvents( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(gdlwxFrame::OnText),text);
5447 if (report) this->AddToDesiredEvents( wxEVT_COMMAND_TEXT_PASTE, wxClipboardTextEventHandler(gdlwxFrame::OnTextPaste),text);
5448 if (report) this->AddToDesiredEvents( wxEVT_COMMAND_TEXT_CUT, wxClipboardTextEventHandler(gdlwxFrame::OnTextCut),text);
5449 if (report) this->AddToDesiredEvents( wxEVT_LEFT_DOWN, wxMouseEventHandler(gdlwxFrame::OnTextMouseEvents),text);
5450 if (report) this->AddToDesiredEvents( wxEVT_LEFT_UP, wxMouseEventHandler(gdlwxFrame::OnTextMouseEvents),text);
5451 if (report) this->AddToDesiredEvents( wxEVT_MIDDLE_DOWN, wxMouseEventHandler(gdlwxFrame::OnTextMouseEvents),text);
5452
5453 // UPDATE_WINDOW
5454 REALIZE_IF_NEEDED
5455 }
SetWidgetSize(DLong sizex,DLong sizey)5456 void GDLWidgetText::SetWidgetSize(DLong sizex, DLong sizey)
5457 {
5458
5459 START_CHANGESIZE_NOEVENT
5460
5461 wxWindow* me = dynamic_cast<wxWindow*> (this->GetWxWidget());
5462 if (me == NULL) {
5463 #ifdef GDL_DEBUG_WIDGETS
5464 wxMessageOutputStderr().Printf(_T("GDLWidgetText::SetSize of non wxWindow %s\n"), this->GetWidgetName().c_str());
5465 #endif
5466 return;
5467 }
5468 //widget text size is in LINES in Y and CHARACTERS in X. But overridden by scr_xsize et if present
5469 wxRealPoint widgetSize = wxRealPoint(-1,-1);
5470 static std::string testExtent("M");
5471 wxSize fontSize=calculateTextScreenSize(testExtent); //use text extent of an EM for realistic fontSize.
5472 int lineHeight=fontSize.y;
5473 wxSize currentSize=me->GetClientSize();
5474
5475 //for each x or y, if >0 take the new value in textSize, and correct wSize to take into account possible wxWidgets-induced scrollbars.
5476 // if ==0 take the initial textSize value
5477 // if < 0 use current textSize.
5478 // all pixels values are recomputed as we need to take care of spurious scrollbars.
5479 if (sizex > 0) textSize.x=sizex; else if (sizex == 0) textSize.x=initialSize.x;
5480
5481 if (sizey > 0) textSize.y=sizey; else if (sizey == 0) textSize.y=initialSize.y;
5482
5483 //proceed as in computeWidgetSize() , same code, except that textSize is never -1.
5484 widgetSize.x = (textSize.x) * fontSize.x;
5485 if (textSize.y > 1) widgetSize.y = textSize.y * lineHeight; else widgetSize.y = lineHeight;
5486
5487 if (textSize.y == 1) widgetSize.y+=2*gdlTEXT_SPACE; //for margin
5488 if (scrolled && textSize.y > 1) widgetSize.x+=gdlSCROLL_WIDTH_Y;
5489
5490 //if multiline and no hscroll, a x-axis scrollbar will be added by wxWidgets if longestLineSize cannot be shown, and we cannot do anything about it.
5491 //multiline here is "if (multiline) textStyle |= wxTE_MULTILINE;"
5492 if (!scrolled) {if (textSize.y > 1 && (textSize.x < maxlinelength) ) widgetSize.y += gdlSCROLL_HEIGHT_X; }
5493 else if (textSize.y > 1 && widgetSize.x < (maxlinelength*fontSize.x+gdlSCROLL_WIDTH_Y) ) {
5494 widgetSize.y += gdlSCROLL_HEIGHT_X;
5495 }
5496 widgetSize.x+=2*gdlTEXT_SPACE; //for margin
5497
5498 int x = ceil(widgetSize.x);
5499 int y = ceil(widgetSize.y);
5500 wSize = wxSize(x,y); //update current widgetSize.
5501 me->SetClientSize(wSize);
5502 me->SetMinClientSize(wSize);
5503 if (!widgetSizer) if (framePanel) framePanel->Fit();
5504
5505 UPDATE_WINDOW
5506
5507 END_CHANGESIZE_NOEVENT
5508
5509 #ifdef GDL_DEBUG_WIDGETS
5510 wxMessageOutputStderr().Printf(_T("GDLWidgetList::SetSize %d,%d (%s)\n"), sizex, sizey, this->GetWidgetName().c_str());
5511 #endif
5512 }
5513
~GDLWidgetText()5514 GDLWidgetText::~GDLWidgetText(){
5515 #ifdef GDL_DEBUG_WIDGETS
5516 std::cout << "~GDLWidgetText(" << widgetID <<")"<< std::endl;
5517 #endif
5518 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
5519 }
5520
ChangeText(DStringGDL * valueStr,bool noNewLine_)5521 void GDLWidgetText::ChangeText( DStringGDL* valueStr, bool noNewLine_)
5522 {
5523 delete vValue;
5524 vValue = valueStr;
5525 DString value = "";
5526
5527 bool doNotAddNl=(noNewLine_ || (!multiline) );
5528
5529 nlines=0;
5530 for( int i=0; i<valueStr->N_Elements(); ++i)
5531 {
5532 value += (*valueStr)[ i];
5533 if ( !doNotAddNl )
5534 #ifdef _WIN32
5535 {value += "\r\n"; nlines++;}
5536 #else
5537 {value += '\n'; nlines++;}
5538 #endif
5539 }
5540 lastValue = value;
5541 //recompute nlines, maxlinelength from start to be sure
5542 nlines=1;
5543 maxlinelength=0;
5544 const char* s=lastValue.c_str();
5545 int length=0;
5546 for (int i=0; i<lastValue.length(); ++i, ++length)
5547 {
5548 if (s[i]==10) {
5549 maxlinelength=(length>maxlinelength)?length:maxlinelength;
5550 nlines++;
5551 length=0;
5552 }
5553 }
5554 if (length>maxlinelength) maxlinelength=length; //if no last return.
5555
5556 wxString valueWxString = wxString( lastValue.c_str( ), wxConvUTF8 );
5557 if ( theWxWidget != NULL ) {
5558 wxTextCtrl* txt=dynamic_cast<wxTextCtrl*> (theWxWidget);
5559 assert( txt != NULL);
5560 txt->ChangeValue( valueWxString ); //by contrast with SetValue, does not generate an EVENT -- IDL does not either.
5561 } else std::cerr << "Null widget in GDLWidgetText::SetTextValue(), please report!" << std::endl;
5562 //update widgetSize. Important to deal with 'added' scrollbars.
5563 this->SetWidgetSize(-1,-1);
5564 }
5565
InsertText(DStringGDL * valueStr,bool noNewLine_,bool append)5566 void GDLWidgetText::InsertText( DStringGDL* valueStr, bool noNewLine_, bool append) {
5567 wxTextCtrl* txt = dynamic_cast<wxTextCtrl*> (theWxWidget);
5568 assert(txt != NULL);
5569 long from, to;
5570
5571 //wxWidgets bug?
5572 wxTextPos pos=txt->GetLastPosition();
5573 if (pos<=1) {
5574 GDLWidgetText::ChangeText(valueStr,noNewLine_);
5575 return;
5576 }
5577
5578 //really append/replace
5579 if (append) { //see discussion wxTextEntry::GetInsertionPoint() at https://docs.wxwidgets.org/trunk/classwx_text_entry.html
5580 if (multiline) {
5581 txt->SetSelection(pos-1,pos);
5582 } else {
5583 txt->SetSelection(pos,pos);
5584 }
5585 }
5586 txt->GetSelection(&from, &to);
5587 bool doNotAddNl=(noNewLine_ || (!multiline) );
5588
5589 DString value = (doNotAddNl)?"":(!append)?"":"\n";
5590 for ( int i = 0; i < valueStr->N_Elements( ); ++i ) {
5591 int length=(*valueStr)[ i].length();
5592 value += (*valueStr)[ i];
5593 if ( !doNotAddNl ) {
5594 #ifdef _WIN32
5595 value += "\r\n"; nlines++;
5596 #else
5597 value += '\n'; nlines++;
5598 #endif
5599 }
5600 }
5601 //note value.size it will be used
5602 int insertedLength=value.size();
5603 lastValue.replace(from,to-from,value);
5604 //recompute nlines, maxlinelength from start to be sure
5605 nlines=1;
5606 maxlinelength=0;
5607 const char* s=lastValue.c_str();
5608 int length=0;
5609 for (int i=0; i<lastValue.length(); ++i, ++length)
5610 {
5611 if (s[i]==10) {
5612 maxlinelength=(length>maxlinelength)?length:maxlinelength;
5613 nlines++;
5614 length=0;
5615 }
5616 }
5617 if (length>maxlinelength) maxlinelength=length; //if no last return.
5618 delete vValue;
5619 vValue = new DStringGDL(lastValue);
5620 wxString valueWxString = wxString( lastValue.c_str( ), wxConvUTF8 );
5621 if ( theWxWidget != NULL ) {
5622 txt->ChangeValue( valueWxString ); //by contrast with SetValue, does not generate an EVENT (neither does *DL).
5623 txt->SetSelection(from+insertedLength,from+insertedLength);
5624 txt->ShowPosition(from+insertedLength);
5625 } else std::cerr << "Null widget in GDLWidgetText::SetTextValue(), please report!" << std::endl;
5626 //update widgetSize
5627 this->SetWidgetSize(-1,-1);
5628 }
5629
SetTextSelection(DLongGDL * pos)5630 void GDLWidgetText::SetTextSelection(DLongGDL* pos)
5631 { //*DL selection are [start,length] [3,20] -> pos (3,23)
5632 //numerous cases to handle with invalid values (negative, too large).
5633 //Hope it works for all cases:
5634 long from,to,len;
5635 long oldSelStart, oldSelEnd;
5636 wxTextCtrl* txt=dynamic_cast<wxTextCtrl*> (theWxWidget);
5637 assert( txt != NULL);
5638
5639 txt->GetSelection(&oldSelStart,&oldSelEnd);
5640 len = txt->GetLastPosition()+1;
5641
5642 if ((*pos)[0] < 0 ) from=0;
5643 else if ((*pos)[0] > len ) from=len;
5644 else from=(*pos)[0];
5645
5646
5647 if (pos->N_Elements()<2) {
5648 //selection = insertion
5649 txt->SetSelection(from,from);
5650 return;
5651 }
5652 //2 elements, define selection
5653 to=(*pos)[1];
5654
5655 if ( from+to >= len ) {
5656 //set insertion position at end of last selection (?)
5657 txt->SetSelection(oldSelEnd,oldSelEnd);
5658 return;
5659 }
5660 if ( to < 0 ) {
5661 //set insertion position at from
5662 txt->SetSelection(from,from);
5663 return;
5664 }
5665 txt->SetSelection(from,from+to);
5666 }
5667
GetTextSelection()5668 DLongGDL* GDLWidgetText::GetTextSelection()
5669 {
5670 DLongGDL* pos=new DLongGDL(dimension(2),BaseGDL::ZERO);
5671 long from,to;
5672 wxTextCtrl* txt=dynamic_cast<wxTextCtrl*> (theWxWidget);
5673 assert( txt != NULL);
5674
5675 txt->GetSelection(&from,&to);
5676 (*pos)[0]=from; (*pos)[1]=to-from;
5677 return pos;
5678 }
5679
GetSelectedText()5680 DStringGDL* GDLWidgetText::GetSelectedText()
5681 {
5682 wxTextCtrl* txt=dynamic_cast<wxTextCtrl*>(theWxWidget);
5683 assert( txt != NULL);
5684
5685 return new DStringGDL(txt->GetStringSelection().mb_str(wxConvUTF8).data());
5686 }
5687
GDLWidgetLabel(WidgetIDT p,EnvT * e,const DString & value_,DULong eventflags,bool sunken_)5688 GDLWidgetLabel::GDLWidgetLabel( WidgetIDT p, EnvT* e, const DString& value_ , DULong eventflags, bool sunken_)
5689 : GDLWidget( p, e , NULL, eventflags )
5690 , value(value_)
5691 , sunken(sunken_)
5692 {
5693 GDLWidget* gdlParent = GetWidget( parentID );
5694 widgetPanel = GetParentPanel( );
5695 widgetSizer = GetParentSizer( );
5696
5697 if (sunken) frameWidth=0;
5698
5699 widgetStyle=widgetAlignment();
5700 const wxString valueWxString = wxString( value.c_str( ), wxConvUTF8 );
5701
5702 bool simplelabel=(wSize.x < 0 && frameWidth <1 && !sunken); //before recomputing wSize!
5703 wSize=computeWidgetSize();
5704 //to comply with the positioning observed with IDL, a label with a defined size is in fact a label inside a (possibly invisible) frame of such size.
5705 //the centering of the label is 'center' by default and does not inherit from the parent base default centering (it is the frame that inherits), but if
5706 //a centering is required, it is done.
5707 //labels with no particular size and frames are made idem.
5708 //label with no particular size and no frame are aligned normally, i.e., they inherit if the alignment is not precised.
5709 // the simple case is
5710 if (simplelabel) {
5711 wxStaticText* label = new wxStaticText( widgetPanel, widgetID, wxT(""), wOffset, wxDefaultSize, wxST_NO_AUTORESIZE|widgetStyle);
5712 label->SetLabelText(valueWxString);
5713 label->SetSize(wSize);
5714 label->SetMinSize(wSize);
5715 label->Wrap(-1);
5716 theWxContainer = theWxWidget = label;
5717 if (widgetSizer) widgetSizer->Add(label, DONOTALLOWSTRETCH, widgetStyle|wxALL, gdlSPACE);
5718 if (widgetSizer) widgetSizer->Fit(label); else widgetPanel->Fit();
5719 // UPDATE_WINDOW
5720 REALIZE_IF_NEEDED
5721 return;
5722 }
5723 //Now more complicated. Framed is not Sunken. Framed implies adding 2 panels, one 'extruded'.
5724 //the inside panel is of (eventually fixed) size wSize. It contains the text, aligned.
5725 //sizers should link all those sizes
5726 framePanel = new wxPanel(widgetPanel, wxID_ANY, wOffset, wxDefaultSize, sunken?wxBORDER_SUNKEN:(frameWidth >0 )?gdlBORDER_EXT:wxBORDER_NONE);
5727 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
5728 framePanel->SetBackgroundColour(wxColour(0x3a, 0x82, 0x56)); //vert fonce
5729 #endif
5730 wxSizer* frameSizer = new wxBoxSizer(wxVERTICAL);
5731 framePanel->SetSizer(frameSizer);
5732 wxStaticText* label;
5733 if (frameWidth >0) {
5734 //the inside panel, framed
5735 wxPanel* hiddenPanel = new wxPanel(framePanel);
5736 frameSizer->Add(hiddenPanel, DONOTALLOWSTRETCH, wxALL | wxEXPAND, frameWidth);
5737 hiddenPanel->SetSize(wSize);
5738 hiddenPanel->SetMinSize(wSize);
5739 wxSizer* sz = new wxBoxSizer(wxVERTICAL);
5740 hiddenPanel->SetSizer(sz);
5741 //the label, with special style inside
5742 int style = labelTextAlignment();
5743 //create and position label in panel
5744 label = new wxStaticText(hiddenPanel, widgetID, valueWxString);
5745 label->Wrap(-1);
5746 sz->Add(label, DONOTALLOWSTRETCH, style | wxALL, 0);
5747 sz->Fit(label);
5748 frameSizer->Fit(hiddenPanel);
5749 framePanel->Fit();
5750 } else {
5751 framePanel->SetSize(wSize);
5752 framePanel->SetMinSize(wSize);
5753 //the label, with special style inside
5754 int style= labelTextAlignment();
5755 //create and position label in panel
5756 label = new wxStaticText( framePanel, widgetID, valueWxString);
5757 label->Wrap(-1);
5758 frameSizer->Add(label,DONOTALLOWSTRETCH,style|wxALL,0);
5759 frameSizer->Fit(label); //sz exist always
5760 }
5761 theWxContainer=framePanel;
5762 theWxWidget=label;
5763 if (widgetSizer) widgetSizer->Add(framePanel, DONOTALLOWSTRETCH, widgetStyle|wxALL, 0);
5764 if (widgetSizer) widgetSizer->Fit(framePanel); else widgetPanel->Fit();
5765 // UPDATE_WINDOW
5766 REALIZE_IF_NEEDED
5767 }
5768
~GDLWidgetLabel()5769 GDLWidgetLabel::~GDLWidgetLabel(){
5770 #ifdef GDL_DEBUG_WIDGETS
5771 std::cout << "~GDLWidgetLabel(" << widgetID << ")" << std::endl;
5772 #endif
5773 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
5774 }
SetWidgetSize(DLong sizex,DLong sizey)5775 void GDLWidgetLabel::SetWidgetSize(DLong sizex, DLong sizey) //in pixels. Always.
5776 {
5777 START_CHANGESIZE_NOEVENT
5778 //Sizes are in pixels. Units must be converted before calling this function.
5779 wxWindow* me=static_cast<wxWindow*>(theWxContainer);
5780 //a graphic window cannot be larger than the base widget it is in, if the base widget size has been fixed
5781 wxSize currentSize=me->GetSize();
5782 wxSize currentBestSize=me->GetBestSize();
5783 #ifdef GDL_DEBUG_WIDGETS
5784 wxMessageOutputStderr( ).Printf( _T( "GDLWidgetLabel::SetSize currentSize=%d,%d\n"),currentSize.x,currentSize.y);
5785 #endif
5786 //unprecised sizes do not change
5787 if (sizex == -1) sizex = currentSize.x;
5788 if (sizey == -1) sizey = currentSize.y;
5789
5790 if (widgetSizer) {
5791 //passed zeroes = mr sizer, do your best..
5792 if (sizex == 0) sizex = -1;
5793 if (sizey == 0) sizey = -1;
5794 } else {
5795 //passed zeroes = your best is to keep best size (in cache, value defined at creation)
5796 if (sizex == 0) sizex = currentBestSize.x;
5797 if (sizey == 0) sizey = currentBestSize.y;
5798 }
5799 wSize.x = sizex;
5800 wSize.y = sizey;
5801 me->SetSize(wSize);
5802 //the sizer takes care of the eventual frame
5803 me->SetMinSize(wSize);
5804
5805 UPDATE_WINDOW
5806
5807 END_CHANGESIZE_NOEVENT
5808
5809
5810 #ifdef GDL_DEBUG_WIDGETS
5811 wxMessageOutputStderr( ).Printf( _T( "GDLWidget::SetSize %d,%d (%s)\n"),sizex,sizey,this->GetWidgetName().c_str());
5812 #endif
5813 }
5814
SetLabelValue(const DString & value_)5815 void GDLWidgetLabel::SetLabelValue(const DString& value_) {
5816 value = value_;
5817 //update vValue
5818 delete(vValue);
5819 vValue = new DStringGDL(value);
5820
5821 wxString valueWxString = wxString(value_.c_str(), wxConvUTF8);
5822 if (theWxWidget != NULL) {
5823 wxStaticText *label = dynamic_cast<wxStaticText*> (theWxWidget);
5824 if (label) {
5825 label->SetLabelText(valueWxString);
5826 if (this->IsDynamicResize()) {
5827 wSize = wxSize(-1, -1);
5828 wSize = computeWidgetSize();
5829 label->SetMinSize(wSize);
5830 label->SetSize(wSize);
5831 //special for labels:
5832 if (theWxContainer && theWxContainer != theWxWidget) {
5833 wxPanel* p = static_cast<wxPanel*> (theWxContainer);
5834 if (p) {
5835 // this looks complicated but how to do otherwise?
5836 p->SetMinSize(label->GetBestSize()+wxSize(2*frameWidth,2*frameWidth));
5837 }
5838 }
5839 }
5840 }
5841 else cerr << "Warning GDLWidgetLabel::SetLabelValue(): widget type confusion\n";
5842 //SetLabel, unless SetLabelText, interprets markup (<b></b> etc)
5843 } else std::cerr << "Null widget in GDLWidgetLabel::SetLabelValue(), please report!" << std::endl;
5844 }
5845
5846 //propertysheet. Unsupported as need to be completely rewritten as the other widgets are (new code) and not able to test.
5847 #ifdef HAVE_WXWIDGETS_PROPERTYGRID
5848 //
5849 // GDLWidgetPropertySheet::GDLWidgetPropertySheet( WidgetIDT parentID, EnvT* e)
5850 // : GDLWidget( p, e , value, eventflag)
5851 //{
5852 // GDLWidget* gdlParent = GetWidget( parentID );
5853 // widgetPanel = GetParentPanel( );
5854 // widgetSizer = GetParentSizer( );
5855 // topWidgetSizer = this->GetTopLevelBaseWidget(parentID)->GetSizer();
5856 // // Construct wxPropertyGrid control
5857 // wxPropertyGrid* pg = new wxPropertyGrid(gdlParent,widgetID,wxDefaultPosition,wxDefaultSize,
5858 // // Here are just some of the supported window styles
5859 // wxPG_AUTO_SORT | // Automatic sorting after items added
5860 // wxPG_SPLITTER_AUTO_CENTER | // Automatically center splitter until user manually adjusts it
5861 // // Default style
5862 // wxPG_DEFAULT_STYLE );
5863 //// Window style flags are at premium, so some less often needed ones are
5864 //// available as extra window styles (wxPG_EX_xxx) which must be set using
5865 //// SetExtraStyle member function. wxPG_EX_HELP_AS_TOOLTIPS, for instance,
5866 //// allows displaying help strings as tool tips.
5867 // pg->SetExtraStyle( wxPG_EX_HELP_AS_TOOLTIPS );
5868 //
5869 // theWxWidget=pg;
5870 //
5871 // // Add int property
5872 //pg->Append( new wxIntProperty("IntProperty", wxPG_LABEL, 12345678) );
5873 //// Add float property (value type is actually double)
5874 //pg->Append( new wxFloatProperty("FloatProperty", wxPG_LABEL, 12345.678) );
5875 //// Add a bool property
5876 //pg->Append( new wxBoolProperty("BoolProperty", wxPG_LABEL, false) );
5877 //// A string property that can be edited in a separate editor dialog.
5878 //pg->Append( new wxLongStringProperty("LongStringProperty",
5879 //wxPG_LABEL,
5880 //"This is much longer string than the "
5881 //"first one. Edit it by clicking the button."));
5882 //// String editor with dir selector button.
5883 //pg->Append( new wxDirProperty("DirProperty", wxPG_LABEL, ::wxGetUserHome()) );
5884 //// wxArrayStringProperty embeds a wxArrayString.
5885 //pg->Append( new wxArrayStringProperty("Label of ArrayStringProperty",
5886 //"NameOfArrayStringProp"));
5887 //// A file selector property.
5888 //pg->Append( new wxFileProperty("FileProperty", wxPG_LABEL, wxEmptyString) );
5889 //
5890 //UPDATE_WINDOW; REALIZE_IF_NEEDED;
5891 //}
5892 #endif
5893 // GDL widgets =====================================================
5894 // GDLFrame ========================================================
gdlwxFrame(wxWindow * parent,GDLWidgetTopBase * gdlOwner_,wxWindowID id,const wxString & title,const wxPoint & pos,const wxSize & size,long style)5895 gdlwxFrame::gdlwxFrame( wxWindow* parent, GDLWidgetTopBase* gdlOwner_, wxWindowID id, const wxString& title , const wxPoint& pos, const wxSize& size, long style)
5896 : wxFrame()
5897 , mapped( false )
5898 , frameSize(size)
5899 , gdlOwner( gdlOwner_)
5900 {
5901 Create ( parent, id, title, pos, size, style );
5902 m_resizeTimer = new wxTimer(this,RESIZE_TIMER);
5903 }
5904
~gdlwxFrame()5905 gdlwxFrame::~gdlwxFrame()
5906 {
5907 if (m_resizeTimer->IsRunning()) m_resizeTimer->Stop();
5908 #ifdef GDL_DEBUG_WIDGETS
5909 std::cout << "~GDLFrame: " << this << std::endl;
5910 #endif
5911 //frame is part of a TLB. if frame is destroyed, destroy TLB if still existing.
5912 if( gdlOwner != NULL)
5913 {
5914 #ifdef GDL_DEBUG_WIDGETS
5915 std::cout << "~GDLFrame: Destroying Base Container" << gdlOwner->GetWidgetID() << std::endl;
5916 #endif
5917 // gdlOwner->NullWxWidget( ); //remove one's reference from container
5918 // gdlOwner->SelfDestroy( ); // send delete request to GDL owner = container.
5919 }
5920 }
5921 // Phantom frame
gdlwxPhantomFrame()5922 gdlwxPhantomFrame::gdlwxPhantomFrame()
5923 : wxFrame(NULL,wxID_ANY,wxString("phantom"),wxDefaultPosition,wxDefaultSize,wxFRAME_TOOL_WINDOW)
5924 {
5925 wxScrolled<wxPanel>* test = new wxScrolled<wxPanel>(this); //to measure scrollbars
5926 test->ShowScrollbars(wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS);
5927 }
5928
Realize()5929 void gdlwxPhantomFrame::Realize() {
5930 wxWindow* c=this->GetChildren()[0];
5931 //retrieve toolkit's width and height of scrollbars (useful to calculate sizes for widgets)
5932 wxSize s=c->GetSize();
5933 wxSize e=c->GetClientSize();
5934 wxSize w=s-e;
5935 // std::cerr<<w.x<<","<<w.y<<std::endl;
5936 if (w.x <= 0) w.x=gdlABSENT_SIZE_VALUE;
5937 if (w.y <= 0) w.y=gdlABSENT_SIZE_VALUE;
5938 sysScrollHeight=w.y;
5939 sysScrollWidth=w.x;
5940 }
5941
5942 // Frame for Plots ========================================================
gdlwxPlotFrame(const wxString & title,const wxPoint & pos,const wxSize & size,long style,bool scrolled_)5943 gdlwxPlotFrame::gdlwxPlotFrame( const wxString& title , const wxPoint& pos, const wxSize& size, long style, bool scrolled_)
5944 : wxFrame( NULL, wxID_ANY, title, pos, size, style )
5945 , frameSize(size)
5946 , scrolled(scrolled_)
5947 {
5948 m_resizeTimer = new wxTimer(this,RESIZE_PLOT_TIMER);
5949 }
5950
~gdlwxPlotFrame()5951 gdlwxPlotFrame::~gdlwxPlotFrame() {
5952 //We are here outside gdl widget hierarchy. If we Destroy the frame, everything goes.
5953 // However, we MUST insure this is equivalent to "WDELETE" because the complicated interplay of multidevices, plplot streams, and widgets.
5954 // So it is better to pass and wait for the deletion of the contained window id (by marking it unValid) and let TidyWindowsList clear everything.
5955 // this widget will be actually destroyed when the inside GraphicsPanel will be destroyed.
5956 if (m_resizeTimer->IsRunning()) m_resizeTimer->Stop();
5957 #ifdef GDL_DEBUG_WIDGETS
5958 std::cout << "~gdlwxPlotFrame: " << this << std::endl;
5959 #endif
5960 }
5961
Realize()5962 void gdlwxPlotFrame::Realize() {
5963 #ifdef GDL_DEBUG_WIDGETS
5964 wxMessageOutputStderr().Printf(_T("gdlwxPlotFrame:Realize\n"));
5965 #endif
5966 }
5967
5968 //version using wxBG_STYLE_PAINT and blit to an AutoBufferedPaintDC, will this improve speed?
gdlwxGraphicsPanel(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)5969 gdlwxGraphicsPanel::gdlwxGraphicsPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
5970 : wxScrolled<wxPanel>() // Use default ctor here!
5971 , pstreamIx( -1 )
5972 , pstreamP( NULL )
5973 , wx_dc( NULL)
5974 , drawSize(size)
5975 {
5976 // Do this first:
5977 SetBackgroundStyle(wxBG_STYLE_PAINT);
5978 Create( parent, id, pos, size, style, name );
5979 }
5980 //gdlwxGraphicsPanel::gdlwxGraphicsPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
5981 //: wxScrolled<wxPanel>( parent, id, pos, size, style, name )
5982 //, pstreamIx( -1 )
5983 //, pstreamP( NULL )
5984 //, m_dc( NULL)
5985 //, drawSize(size)
5986 //{ }
GetStream()5987 GDLWXStream* gdlwxGraphicsPanel::GetStream(){return pstreamP;};
DeleteUsingWindowNumber()5988 void gdlwxGraphicsPanel::DeleteUsingWindowNumber(){
5989 pstreamP->SetValid(false);
5990 GraphicsDevice::GetGUIDevice()->TidyWindowsList(); //tidy Window List will delete widget by itself
5991 }
SetStream(GDLWXStream * s)5992 void gdlwxGraphicsPanel::SetStream(GDLWXStream* s) {
5993 pstreamP = s;
5994 wx_dc = pstreamP->GetStreamDC();
5995 }
gdlwxPlotPanel(gdlwxPlotFrame * parent)5996 gdlwxPlotPanel::gdlwxPlotPanel( gdlwxPlotFrame* parent) //, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
5997 : gdlwxGraphicsPanel::gdlwxGraphicsPanel(parent)
5998 , myFrame(parent)
5999 {
6000 #ifdef GDL_DEBUG_WIDGETS
6001 std::cout << "gdlwxPlotPanel::gdlwxPlotPanel(" << this << ") called."<< std::endl;
6002 #endif
6003 this->SetBackgroundColour(*wxBLACK);
6004 }
6005
RepaintGraphics(bool doClear)6006 void gdlwxGraphicsPanel::RepaintGraphics(bool doClear) {
6007 wxClientDC dc(this); //is a scrolled window: needed
6008 DoPrepareDC(dc); //you probably do not want to call wxScrolled::PrepareDC() on wxAutoBufferedPaintDC as it already does this internally for the real underlying wxPaintDC.
6009 // dc.SetDeviceClippingRegion(GetUpdateRegion());
6010 if (doClear) dc.Clear();
6011 dc.Blit(0, 0, drawSize.x, drawSize.y, wx_dc, 0, 0);
6012 }
6013
gdlwxDrawPanel(wxWindow * parent,wxWindowID id,const wxPoint & pos,const wxSize & size,long style,const wxString & name)6014 gdlwxDrawPanel::gdlwxDrawPanel( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
6015 : gdlwxGraphicsPanel::gdlwxGraphicsPanel(parent, id, pos, size, style, name )
6016 , myWidgetDraw(static_cast<GDLWidgetDraw*>(GDLWidget::GetWidget(id)))
6017 {
6018 #ifdef GDL_DEBUG_WIDGETS
6019 std::cout << "gdlwxDrawPanel::gdlwxDrawPanel(" << this << ") called."<< std::endl;
6020 #endif
6021 }
6022
InitStream(int wIx)6023 void gdlwxDrawPanel::InitStream(int wIx)
6024 {
6025 if (wIx < 0) pstreamIx = GraphicsDevice::GetGUIDevice( )->WAddFree( );
6026 else pstreamIx = wIx;
6027 if ( pstreamIx == -1 ) throw GDLException( "Failed to allocate GUI stream." );
6028 pstreamP = static_cast<GDLWXStream*>(GraphicsDevice::GetGUIDevice( )->GUIOpen( pstreamIx, drawSize.x, drawSize.y, this ));
6029 if( pstreamP == NULL)
6030 {
6031 throw GDLException( "Failed to open GUI stream: " + i2s( pstreamIx ) );
6032 }
6033 wx_dc = pstreamP->GetStreamDC( );
6034 }
6035
ResizeDrawArea(wxSize s)6036 void gdlwxGraphicsPanel::ResizeDrawArea(wxSize s)
6037 {
6038 bool doClear=false;
6039 if (drawSize.x > s.x || drawSize.y > s.y ) doClear=true;
6040 drawSize=s;
6041 this->SetVirtualSize(drawSize);
6042 pstreamP->SetSize(drawSize);
6043 RepaintGraphics(doClear);
6044 }
6045
~gdlwxPlotPanel()6046 gdlwxPlotPanel::~gdlwxPlotPanel()
6047 {
6048 #ifdef GDL_DEBUG_WIDGETS
6049 std::cout << "~gdlwxPlotPanel() :" << this << "pstreamP="<<GetStream()<< " is now invalid."<<std::endl;
6050 #endif
6051 this->GetMyFrame()->Show(false);
6052 this->GetMyFrame()->Destroy(); //will be really destroyed after next call to wxApp (remember, wxApp is not running, only GDL is running).
6053 }
6054
~gdlwxDrawPanel()6055 gdlwxDrawPanel::~gdlwxDrawPanel()
6056 {
6057 //widget_control,this,/dest actually calls wdelete. So the only case where we are not 'deleted' with a wdelete or widget_control command is during the detetion of a container.
6058 // in which case, we avoid reentrance because on the first pass the stream has been invalidated.
6059 // if associated stream is invalid, do nothing : 'this' has already been called. Normally, should not happen...
6060 if (pstreamP->GetValid()) return;
6061
6062 //invalidate stream in any case, but do not have TidyWindowsList() re-deleting it, as whatever call us, gdlwxDrawPanel is going to die.
6063 pstreamP->SetValid(false);
6064 #ifdef GDL_DEBUG_WIDGETS
6065 std::cout << "~gdlwxDrawPanel() :" << this << "pstreamP="<<GetStream()<< " is now invalid."<<std::endl;
6066 #endif
6067
6068 GraphicsDevice::GetGUIDevice()->TidyWindowsList(false);
6069 // get WIDGET_DRAW
6070 GDLWidgetDraw* d = GetMyWidget();
6071 // at exit from here, widget_draw is either destroyed because I ask for it or because it was already being destroyed. To prevent reentrance, NULL the reference to it.
6072 myWidgetDraw = NULL;
6073 //either widget_draw is valid and we must destroy it properly. Else it is not anymore (see ~GDLWidgetDraw() ) so we have nothing to do.
6074 if (d && d->IsValid()) { //we come from wdelete
6075 //this=thewxWidget will be destroyed no matter what, since this is part of its destruction process. To destroy the gdlwidget, it would need to remove 'this' from the
6076 //gdlWidget structure and the underlying wxwidgets parent-child lists. Difficult. Simpler at the moment:
6077 // unref the container (so destruction call of the wxcontainer will not be effected at widget destruction)
6078 // delete the wigdet to remove it from widget hierarchy.
6079 wxWindow* delayed_destroy_frame = static_cast<wxWindow*>(d->GetWxContainer()); //container can be theWxWidget=this
6080 d->UnrefTheWxContainer(); //in any cases
6081 //remove the container from its parent (panel)
6082 delayed_destroy_frame->GetParent()->RemoveChild(delayed_destroy_frame); //should hide the wxContainer.
6083 delayed_destroy_frame->Hide();
6084 //no link anymore to 'this' in gdlwidget destruction
6085 delete d;
6086 }
6087 }
GDLWidgetDraw(WidgetIDT p,EnvT * e,int windowIndex,DLong x_scroll_size,DLong y_scroll_size,bool app_scroll,DULong eventFlags_,DStringGDL * drawToolTip)6088 GDLWidgetDraw::GDLWidgetDraw( WidgetIDT p, EnvT* e, int windowIndex,
6089 DLong x_scroll_size, DLong y_scroll_size, bool app_scroll, DULong eventFlags_, DStringGDL* drawToolTip)
6090 : GDLWidget( p, e, NULL, eventFlags_)
6091 , pstreamIx(windowIndex)
6092 {
6093 // xsize,ysize (or, scr_xsize, scr_ysize) define the plot size.
6094 assert( parentID != GDLWidget::NullID);
6095 wSize = computeWidgetSize();
6096 if (widgetSizer==NULL) {
6097 if (wSize.x < 1) wSize.x=gdlDEFAULT_XSIZE;
6098 if (wSize.y < 1) wSize.y=gdlDEFAULT_YSIZE;
6099 }
6100 //get immediately rid of scroll sizes in case of scroll or not... Here is the logic:
6101 // Note that IDL reports wrong dimensions when size and scr_xsize are used simultaneously for at least widget_draw.
6102
6103 if (x_scroll_size > 0) {scrolled=true;x_scroll_size*=unitConversionFactor.x;x_scroll_size+=gdlSCROLL_WIDTH_Y;}
6104 if (y_scroll_size > 0) {scrolled=true;y_scroll_size*=unitConversionFactor.y;y_scroll_size+=gdlSCROLL_HEIGHT_X;}
6105 if (scrolled) {
6106 if (x_scroll_size < 1) x_scroll_size = gdlDEFAULT_XSIZE+gdlSCROLL_WIDTH_Y;
6107 if (y_scroll_size < 1) y_scroll_size = gdlDEFAULT_YSIZE+gdlSCROLL_HEIGHT_X;
6108 }
6109 wScrollSize = scrolled ? wxSize(x_scroll_size , y_scroll_size ) : wSize;
6110
6111 GDLWidget* gdlParent = GetWidget( parentID);
6112 widgetPanel = GetParentPanel( );
6113 widgetSizer = GetParentSizer( );
6114
6115 START_ADD_EVENTUAL_FRAME
6116
6117 widgetStyle = widgetAlignment();
6118 long style = 0;
6119
6120 gdlwxDrawPanel* draw = new gdlwxDrawPanel( widgetPanel, widgetID, wxDefaultPosition, wxDefaultSize, style);
6121 #ifdef GDL_DEBUG_WIDGETS_COLORIZE
6122 draw->SetBackgroundColour(wxColour(0,255,255));
6123 #endif
6124 draw->SetMinClientSize(wScrollSize);
6125 draw->SetClientSize(wScrollSize);
6126 draw->SetVirtualSize(wSize);
6127 draw->InitDrawSize(wSize);
6128
6129 if (scrolled) {
6130 draw->SetScrollbars(gdlSCROLL_RATE, gdlSCROLL_RATE, wSize.x / gdlSCROLL_RATE, wSize.y / gdlSCROLL_RATE);
6131 draw->ShowScrollbars(wxSHOW_SB_ALWAYS, wxSHOW_SB_ALWAYS);
6132 }
6133
6134
6135 draw->SetCursor(wxCURSOR_CROSS);
6136 if (drawToolTip) dynamic_cast<wxWindow*>(draw)->SetToolTip( wxString((*drawToolTip)[0].c_str(),wxConvUTF8));
6137 theWxContainer = theWxWidget = draw;
6138
6139 END_ADD_EVENTUAL_FRAME
6140 TIDY_WIDGET(gdlBORDER_SPACE)
6141
6142 draw->InitStream(windowIndex);
6143
6144 pstreamIx = draw->PStreamIx();
6145 GDLDelete( vValue);
6146 vValue = new DLongGDL(pstreamIx);
6147
6148 //these widget specific events are always set:
6149 this->AddToDesiredEvents( wxEVT_PAINT, wxPaintEventHandler(gdlwxDrawPanel::OnPaint),draw);
6150 // this->AddToDesiredEvents( wxEVT_SIZE, wxSizeEventHandler(gdlwxDrawPanel::OnSize),draw);
6151 //disable flicker see https://wiki.wxwidgets.org/Flicker-Free_Drawing
6152 this->AddToDesiredEvents( wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(gdlwxDrawPanel::OnErase),draw);
6153
6154 //other set event handling according to flags
6155 if (eventFlags & GDLWidget::EV_MOTION) this->AddToDesiredEvents( wxEVT_MOTION, wxMouseEventHandler(gdlwxDrawPanel::OnMouseMove),draw);
6156 // if ( eventFlags & GDLWidget::EV_DROP) nothing to do yet, fixme!;
6157 if ( eventFlags & GDLWidget::EV_EXPOSE) this->AddToDesiredEvents(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(gdlwxDrawPanel::OnErase),draw);
6158 // if ( eventFlags & GDLWidget::EV_VIEWPORT) idem;
6159 if ( eventFlags & GDLWidget::EV_WHEEL) this->AddToDesiredEvents( wxEVT_MOUSEWHEEL, wxMouseEventHandler(gdlwxDrawPanel::OnMouseWheel),draw);
6160 if ( eventFlags & GDLWidget::EV_BUTTON) {
6161 this->AddToDesiredEvents(wxEVT_LEFT_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown),draw);
6162 this->AddToDesiredEvents(wxEVT_LEFT_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp),draw);
6163 this->AddToDesiredEvents(wxEVT_LEFT_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown),draw);
6164 this->AddToDesiredEvents(wxEVT_MIDDLE_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown),draw);
6165 this->AddToDesiredEvents(wxEVT_MIDDLE_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown),draw);
6166 this->AddToDesiredEvents(wxEVT_MIDDLE_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp),draw);
6167 this->AddToDesiredEvents(wxEVT_RIGHT_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown),draw);
6168 this->AddToDesiredEvents(wxEVT_RIGHT_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown),draw);
6169 this->AddToDesiredEvents(wxEVT_RIGHT_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp),draw);
6170 }
6171 if (eventFlags & GDLWidget::EV_KEYBOARD2 || eventFlags & GDLWidget::EV_KEYBOARD){
6172 this->AddToDesiredEvents(wxEVT_KEY_DOWN, wxKeyEventHandler(gdlwxDrawPanel::OnKey),draw);
6173 this->AddToDesiredEvents(wxEVT_KEY_UP, wxKeyEventHandler(gdlwxDrawPanel::OnKey),draw);
6174 }
6175
6176 // UPDATE_WINDOW
6177 REALIZE_IF_NEEDED
6178 }
6179
~GDLWidgetDraw()6180 GDLWidgetDraw::~GDLWidgetDraw() {
6181 #ifdef GDL_DEBUG_WIDGETS
6182 std::cout << "~GDLWidgetDraw(" << widgetID << ")" << std::endl;
6183 #endif
6184 if (theWxContainer) static_cast<wxWindow*>(theWxContainer)->Destroy();
6185 }
6186
AddEventType(DULong evType)6187 void GDLWidgetDraw::AddEventType( DULong evType){
6188 eventFlags |= evType;
6189 gdlwxDrawPanel* draw=(gdlwxDrawPanel*)theWxWidget;
6190 //this one is for the moment defined globally:
6191 // if ( evType == GDLWidget::EV_TRACKING) {
6192 // draw->Connect(widgetID, wxEVT_ENTER_WINDOW, wxMouseEventHandler(GDLFrame::OnEnterWindow));
6193 // draw->Connect(widgetID, wxEVT_LEAVE_WINDOW, wxMouseEventHandler(GDLFrame::OnLeaveWindow));
6194 // } else
6195 if ( evType == GDLWidget::EV_MOTION) draw->Connect(widgetID, wxEVT_MOTION, wxMouseEventHandler(gdlwxDrawPanel::OnMouseMove));
6196 //else if ( evType == GDLWidget::EV_DROP) nothing to do yet, fixme!;
6197 //else if ( evType == GDLWidget::EV_EXPOSE) nothing to do yet, fixme!;
6198 //else if ( evType == GDLWidget::EV_VIEWPORT) idem;
6199 else if ( evType == GDLWidget::EV_WHEEL) draw->Connect(widgetID, wxEVT_MOUSEWHEEL, wxMouseEventHandler(gdlwxDrawPanel::OnMouseWheel));
6200 else if ( evType == GDLWidget::EV_BUTTON) {
6201 draw->Connect(widgetID, wxEVT_LEFT_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6202 draw->Connect(widgetID, wxEVT_LEFT_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp));
6203 draw->Connect(widgetID, wxEVT_LEFT_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6204 draw->Connect(widgetID, wxEVT_MIDDLE_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6205 draw->Connect(widgetID, wxEVT_MIDDLE_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6206 draw->Connect(widgetID, wxEVT_MIDDLE_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp));
6207 draw->Connect(widgetID, wxEVT_RIGHT_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6208 draw->Connect(widgetID, wxEVT_RIGHT_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6209 draw->Connect(widgetID, wxEVT_RIGHT_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp));
6210 }
6211 else if (evType == GDLWidget::EV_KEYBOARD2 || evType == GDLWidget::EV_KEYBOARD){
6212 draw->Connect(widgetID, wxEVT_KEY_DOWN, wxKeyEventHandler(gdlwxDrawPanel::OnKey));
6213 draw->Connect(widgetID, wxEVT_KEY_UP, wxKeyEventHandler(gdlwxDrawPanel::OnKey));
6214 }
6215 }
6216
RemoveEventType(DULong evType)6217 void GDLWidgetDraw::RemoveEventType( DULong evType){
6218 gdlwxDrawPanel* draw=(gdlwxDrawPanel*)theWxWidget;
6219 //this one is for the moment defined globally:
6220 // if ( evType == GDLWidget::EV_TRACKING) {
6221 // draw->Disconnect(widgetID, wxEVT_ENTER_WINDOW, wxMouseEventHandler(GDLFrame::OnEnterWindow));
6222 // draw->Disconnect(widgetID, wxEVT_LEAVE_WINDOW, wxMouseEventHandler(GDLFrame::OnLeaveWindow));
6223 // } else
6224 if ( evType == GDLWidget::EV_MOTION) draw->Disconnect(widgetID, wxEVT_MOTION, wxMouseEventHandler(gdlwxDrawPanel::OnMouseMove));
6225 //else if ( evType == GDLWidget::EV_DROP) nothing to do yet, fixme!;
6226 //else if ( evType == GDLWidget::EV_EXPOSE) nothing to do yet, fixme!;
6227 //else if ( evType == GDLWidget::EV_VIEWPORT) idem;
6228 else if ( evType == GDLWidget::EV_WHEEL) draw->Disconnect(widgetID, wxEVT_MOUSEWHEEL, wxMouseEventHandler(gdlwxDrawPanel::OnMouseWheel));
6229 else if ( evType == GDLWidget::EV_BUTTON) {
6230 draw->Disconnect(widgetID, wxEVT_LEFT_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6231 draw->Disconnect(widgetID, wxEVT_LEFT_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp));
6232 draw->Disconnect(widgetID, wxEVT_LEFT_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6233 draw->Disconnect(widgetID, wxEVT_MIDDLE_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6234 draw->Disconnect(widgetID, wxEVT_MIDDLE_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6235 draw->Disconnect(widgetID, wxEVT_MIDDLE_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp));
6236 draw->Disconnect(widgetID, wxEVT_RIGHT_DOWN, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6237 draw->Disconnect(widgetID, wxEVT_RIGHT_DCLICK, wxMouseEventHandler(gdlwxDrawPanel::OnMouseDown));
6238 draw->Disconnect(widgetID, wxEVT_RIGHT_UP, wxMouseEventHandler(gdlwxDrawPanel::OnMouseUp));
6239 }
6240 else if (evType == GDLWidget::EV_KEYBOARD2 || evType == GDLWidget::EV_KEYBOARD){
6241 draw->Disconnect(widgetID, wxEVT_KEY_DOWN, wxKeyEventHandler(gdlwxDrawPanel::OnKey));
6242 draw->Disconnect(widgetID, wxEVT_KEY_UP, wxKeyEventHandler(gdlwxDrawPanel::OnKey));
6243 }
6244 eventFlags &= ~evType;
6245 }
6246
SetWidgetVirtualSize(DLong sizex,DLong sizey)6247 void GDLWidgetDraw::SetWidgetVirtualSize(DLong sizex, DLong sizey) {
6248 START_CHANGESIZE_NOEVENT
6249 gdlwxDrawPanel* me = dynamic_cast<gdlwxDrawPanel*> (theWxWidget);
6250 wxSize drawSize=me->GetDrawSize();
6251 if (sizex < 1) sizex=drawSize.x;
6252 if (sizey < 1) sizey=drawSize.y;
6253 #ifdef GDL_DEBUG_WIDGETS
6254 wxMessageOutputStderr().Printf(_T("GDLWidgetDraw::SetWidgetVirtualSize %d,%d\n"), sizex, sizey);
6255 #endif
6256 me->ResizeDrawArea(wxSize(sizex, sizey)); //changes draw area
6257 if (!scrolled) {
6258 wSize=wxSize(sizex, sizey);
6259 me->SetMinClientSize(wSize);
6260 me->SetClientSize(wSize);
6261 }
6262 UpdateGui();
6263 END_CHANGESIZE_NOEVENT
6264 }
6265
6266 //Draw widgets as Base Widgets have a Size that can be SIZE(without scrollbars) or SCR_SIZE(with scrollbars)
SetWidgetSize(DLong sizex,DLong sizey)6267 void GDLWidgetDraw::SetWidgetSize(DLong sizex, DLong sizey) {
6268 START_CHANGESIZE_NOEVENT
6269 gdlwxDrawPanel* me = dynamic_cast<gdlwxDrawPanel*> (theWxWidget);
6270 if (!scrolled) { //size is same as clientSize
6271 if (sizex < 1) sizex = wSize.x;
6272 if (sizey < 1) sizey = wSize.y;
6273 wSize=wxSize(sizex,sizey);
6274 me->SetSize(wSize);
6275 me->SetMinSize(wSize);
6276 me->ResizeDrawArea(wSize); //changes draw area
6277 } else { //value asked is for CLIENT size
6278 if (sizex < 1) sizex = wScrollSize.x;
6279 if (sizey < 1) sizey = wScrollSize.y;
6280 wScrollSize=wxSize(sizex,sizey);
6281 me->SetClientSize(wScrollSize);
6282 me->SetMinClientSize(wScrollSize);
6283 }
6284
6285 #ifdef GDL_DEBUG_WIDGETS
6286 wxMessageOutputStderr().Printf(_T("GDLWidgetDraw::SetWidgetSize %d,%d\n"), sizex, sizey);
6287 #endif
6288 UpdateGui();
6289 END_CHANGESIZE_NOEVENT
6290 }
6291
6292 //Draw widgets as Base Widgets have a Size that can be SIZE(without scrollbars) or SCR_SIZE(with scrollbars)
SetWidgetScreenSize(DLong sizex,DLong sizey)6293 void GDLWidgetDraw::SetWidgetScreenSize(DLong sizex, DLong sizey) {
6294 START_CHANGESIZE_NOEVENT
6295 gdlwxDrawPanel* me = dynamic_cast<gdlwxDrawPanel*> (theWxWidget);
6296 if (!scrolled) { //size is same as clientSize
6297 if (sizex < 1) sizex = wSize.x;
6298 if (sizey < 1) sizey = wSize.y;
6299 wSize=wxSize(sizex,sizey);
6300 me->SetClientSize(wSize);
6301 me->SetMinClientSize(wSize);
6302 me->ResizeDrawArea(wSize); //changes draw area
6303 } else { //value asked is for SIZE
6304 if (sizex < 1) sizex = wScrollSize.x;
6305 if (sizey < 1) sizey = wScrollSize.y;
6306 wScrollSize=wxSize(sizex,sizey);
6307 me->SetSize(wScrollSize);
6308 me->SetMinSize(wScrollSize);
6309 }
6310
6311 #ifdef GDL_DEBUG_WIDGETS
6312 wxMessageOutputStderr().Printf(_T("GDLWidgetDraw::SetWidgetSize %d,%d\n"), sizex, sizey);
6313 #endif
6314 UpdateGui();
6315 END_CHANGESIZE_NOEVENT
6316 }
6317
6318 //for windows, it seems necessary to define our own wxApp and run it manually
6319 // for linux, it is NOT necessary, but thos works OK
6320 // for MacOS /COCOA port, the following code does not work and the widgets are not created.
6321 // (tied_scoped_ptr problem?)
6322 #ifndef __WXMAC__
6323
6324 #include "wx/evtloop.h"
6325 #include "wx/ptr_scpd.h"
6326 wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoop);
6327
OnInit()6328 bool wxAppGDL::OnInit()
6329 {
6330 return true;
6331 }
6332
MainLoop()6333 int wxAppGDL::MainLoop() {
6334 wxEventLoopTiedPtr mainLoop((wxEventLoop **) & m_mainLoop, new wxEventLoop);
6335 m_mainLoop->SetActive(m_mainLoop);
6336 loop = this->GetMainLoop();
6337 if (loop) {
6338 if (loop->IsRunning()) {
6339 while (loop->Pending()) // Unprocessed events in queue
6340 {
6341 loop->Dispatch(); // Dispatch next event in queue
6342 }
6343 }
6344 }
6345 return 0;
6346 }
6347
OnExit()6348 int wxAppGDL::OnExit()
6349 {
6350 std::cout << " In GDLApp::OnExit()" << std::endl;
6351 // Defined in guiThread::OnExit() in gdlwidget.cpp
6352 // std::cout << "Exiting thread (GDLApp::OnExit): " << thread << std::endl;
6353 return 0;
6354 }
6355 #endif
6356
6357 #endif
6358