Use new vnc syntax (with a colon).
[qemu-gui.git] / guibuilder.cpp
blobd6d2a2c5fe012bec9210b746fc5512b8d19a9cb7
1 // For compilers that support precompilation, includes "wx/wx.h"
2 #include "wx/wxprec.h"
4 #ifdef __BORLANDC__
5 #pragma hdrstop
6 #endif
8 #ifndef WX_PRECOMP
9 #include "wx/wx.h"
10 #endif
12 #include "guibuilder.h"
14 #include <wx/statline.h>
16 #ifndef _NO_DOXYGEN_
18 typedef struct _gb_button_ids {
19 /*const*/ wxChar title[15];
20 long id;
21 } gb_button_ids;
23 #endif // _NO_DOXYGEN_
25 // function to set the error from all classes that
26 // reference the sizer producer
27 void SetRealizeError(wxGuiBuilder &owner)
29 owner.SetErrorFlag();
32 //----------------------------------------------------------------------
33 // wxGbParseBuffer
34 //----------------------------------------------------------------------
36 wxChar wxGbParseBuffer::PeekChar(size_t offset) const
38 if(CState().pos + offset >= m_buffer.Len())
39 return wxChar(0);
40 else
41 return m_buffer.GetChar(CState().pos + offset);
44 bool wxGbParseBuffer::IsDigit() const
46 wxChar chr = PeekChar();
47 return (chr >= '0' && chr <= '9');
50 bool wxGbParseBuffer::IsAlpha() const
52 wxChar chr = PeekChar();
53 return (chr >= 'a' && chr <= 'z') ||
54 (chr >= 'A' && chr <= 'Z') ||
55 (chr == '_');
58 bool wxGbParseBuffer::ToLong(size_t &value)
60 wxString strval;
61 value = 0;
63 while(IsDigit())
64 strval.Append(PopChar());
66 if(strval.Len() > 0)
68 long tmpval;
69 if(strval.ToLong(&tmpval))
71 value = (size_t)tmpval;
72 return true;
76 return false;
79 bool wxGbParseBuffer::ToLabel(wxString &value)
81 wxString strval;
82 value.Clear();
84 // first char is always alpha
85 if(!IsAlpha())
86 return false;
87 else
89 strval.Append(PopChar());
91 // now digits are also allowed
92 while(IsAlpha() || IsDigit())
93 strval.Append(PopChar());
96 if(strval.Len() > 0)
98 value = strval;
99 return true;
102 return false;
105 bool wxGbParseBuffer::ToString(wxString &value)
107 wxString strval;
108 value.Clear();
110 // get string
111 if(PeekChar() == wxChar(wxGB_WND_LABEL_START))
113 // pop the first quote
114 PopChar();
116 // go on until end quote or end
117 while(PeekChar() != wxChar(wxGB_WND_LABEL_START))
119 // allow end quote to be used in string
120 if(PeekChar() == wxGB_LABEL_ESCAPE)
121 PopChar();
123 if(PeekChar() != wxChar(0))
124 strval.Append(PopChar());
125 else
126 return false; // premature EOF
130 // ok, now remove the last quote
131 if(PeekChar() == wxChar(wxGB_WND_LABEL_START))
133 PopChar();
134 // wx local hack by marc
135 value = ::wxGetTranslation(strval);
136 return true;
139 return false;
141 wxChar wxGbParseBuffer::PopChar(int times)
143 if(State().pos < m_buffer.Len())
145 wxChar chr = 0;
146 int count = (int)times;
149 chr = m_buffer.GetChar(State().pos);
151 State().col ++;
152 State().pos ++;
154 // update row and column
155 if(chr == '\n' || chr == '\r')
157 State().col = 1;
158 State().row ++;
161 count --;
163 while(count > 0 && chr != wxChar(0));
164 return chr;
167 return wxChar(0);
170 void wxGbParseBuffer::EatWhites()
172 while(1)
174 wxChar chr = PeekChar();
175 // skip normal whites
176 if(chr == wxChar('\t') || chr == wxChar(' ') || chr == wxChar('\n') || chr == wxChar('\r'))
177 PopChar();
178 else if(PeekChar(0) == wxChar('/') && PeekChar(1) == wxChar('*'))
180 PopChar(2);
181 // skip till end of line
182 while(PeekChar(0) != wxChar('*') && PeekChar(1) != wxChar('/'))
184 // eat one that belongs to the comment
185 chr = PopChar();
186 if(chr == wxChar(0))
187 break;
190 PopChar(2); // eat comment
192 else
193 break;
197 bool wxGbParseBuffer::ParseTuple(int &x, int &y)
199 bool parsed = false;
201 // get the X
202 if(IsDigit())
204 size_t tmp;
205 if(ToLong(tmp))
206 x = (int)tmp;
207 else
208 return false;
209 parsed = true;
212 // expect comma, or nothing
213 if(PeekChar() == wxChar(','))
215 // get Y
216 PopChar();
217 if(IsDigit())
219 size_t tmp;
220 if(ToLong(tmp))
221 y = (int)tmp;
222 else
223 return false;
224 parsed = true;
228 return parsed;
231 //----------------------------------------------------------------------
232 // wxGbBaseItem
233 //----------------------------------------------------------------------
235 int wxGbBaseItem::ParseCommonFlags(wxGbParseBuffer &buf, wxSizerFlags &flags,
236 wxString &label)
238 int border = -1, borders = 0; // default indication not used
240 // check for border marker
241 if(buf.PeekChar() == wxChar(wxGB_BORDER_MARK))
243 buf.PopChar();
245 // if we have a number, adjust border
246 if(buf.IsDigit())
248 size_t tmpval;
249 if(buf.ToLong(tmpval))
250 border = (int)tmpval;
251 else
252 border = 0;
255 // go do the flags like 'a' - all, 'l' = left, 'r' = right, 't' = top
256 bool bordering = true;
257 while(bordering)
259 char chr = buf.PeekChar();
260 switch(chr)
262 case wxGB_BORDER_ALL:
263 borders = wxALL;
264 break;
265 case wxGB_BORDER_LEFT:
266 borders |= wxLEFT;
267 break;
268 case wxGB_BORDER_RIGHT:
269 borders |= wxRIGHT;
270 break;
271 case wxGB_BORDER_BOTTOM:
272 borders |= wxBOTTOM;
273 break;
274 case wxGB_BORDER_TOP:
275 borders |= wxTOP;
276 break;
278 default:
279 bordering = false;
280 break;
283 if(bordering)
284 buf.PopChar();
285 else
287 // we must have gotten something here
288 // since the digit was there for the border flags
289 if(borders == 0)
291 ::wxLogError(buf.GetAt() + wxT("Missing border flags!"));
292 return -1;
297 // set the border in the sizerflags
298 if(borders != 0)
300 if(border < 0)
301 flags.Border(borders);
302 else
303 flags.Border(borders, border);
307 // get align flags
308 bool aligning = true;
309 while(aligning)
311 char align = (char)buf.PeekChar();
312 switch(align)
314 case wxGB_EXPAND:
315 // expand flag
316 flags.Expand();
317 break;
318 case wxGB_ALIGN_BOTTOM:
319 // align on bottom, clear top flag
320 flags.Align(wxALIGN_BOTTOM);
321 break;
322 case wxGB_ALIGN_TOP:
323 // align on top, clear top flag
324 flags.Align(wxALIGN_TOP);
325 break;
326 case wxGB_ALIGN_LEFT:
327 // align on left, clear right flag
328 flags.Left();
329 break;
330 case wxGB_ALIGN_RIGHT:
331 // align on right, clear left flag
332 flags.Right();
333 break;
334 case wxGB_ALIGN_CENTER:
335 // align center
336 flags.Center();
337 break;
338 case wxGB_ALIGN_HOR:
339 // align horizontal center
340 flags.Align(wxALIGN_CENTER_HORIZONTAL);
341 break;
342 case wxGB_ALIGN_VER:
343 // align vertical center
344 flags.Align(wxALIGN_CENTER_VERTICAL);
345 break;
346 default:
347 aligning = false;
348 break;
351 // get rid of align char
352 if(aligning)
353 buf.PopChar();
356 // determine the proportional part
357 if(buf.PeekChar() == wxGB_PROPORTION)
359 buf.PopChar();
361 // if we have a number, adjust proportion
362 if(buf.IsDigit())
364 size_t tmpval;
365 if(buf.ToLong(tmpval))
366 flags.Proportion((int)tmpval);
367 else
368 flags.Proportion(0);
370 else
372 ::wxLogError(buf.GetAt() + wxT("Missing proportion number!"));
373 return -1;
377 // now determine if there is a label or not
378 if(buf.PeekChar() == wxChar(wxGB_LABEL_MARK))
380 buf.PopChar();
382 // get the label
383 if(!buf.ToLabel(label))
385 ::wxLogError(buf.GetAt() + wxT("Missing label at end of item"));
386 return -1;
390 return (int)buf.GetPos();
393 bool wxGbBaseItem::Verify(wxGbBaseItem *item)
395 bool result = true;
397 if(item != NULL)
399 // compare labels
400 if(!m_label.IsEmpty() &&
401 item->GetLabel().IsSameAs(m_label))
403 ::wxLogError(wxT("Label '") + m_label + wxT("' is defined more then once!"));
404 result = false;
408 return result;
412 //----------------------------------------------------------------------
413 // wxGbSizerItem
414 //----------------------------------------------------------------------
416 size_t wxGbSizerItem::ScanSizerType(const wxGbParseBuffer &buf)
418 char chr = (char)buf.PeekChar(0),
419 bnd = (char)buf.PeekChar(1);
421 // convert to upper case
422 if(chr >= 'a' && chr <= 'z')
423 chr -= 0x020;
425 // check our sizer type
426 switch(chr)
428 // horizontal sizer
429 case wxGB_SIZER_HTYPE:
430 if(bnd == wxGB_WND_LABEL_START)
431 return wxGB_STATICBOXSIZER_H;
432 else
433 return wxGB_BOXSIZER_H;
435 // vertical sizer
436 case wxGB_SIZER_VTYPE:
437 if(bnd == wxGB_WND_LABEL_START)
438 return wxGB_STATICBOXSIZER_V;
439 else
440 return wxGB_BOXSIZER_V;
441 break;
443 // gridsizer
444 case wxGB_SIZER_GTYPE:
445 return wxGB_GRIDSIZER;
447 // flexgridsizer
448 case wxGB_SIZER_FTYPE:
449 return wxGB_FLEXGRIDSIZER;
453 // return default undefined one
454 return wxGB_UNDEFINED;
457 int wxGbSizerItem::Parse(wxGbParseBuffer &buf)
459 // skip whites and update row / col count
460 buf.EatWhites();
462 int result = 0;
463 m_type = wxGbSizerItem::ScanSizerType(buf);
465 // parse all types of sizers
466 buf.Push();
467 switch(m_type)
469 case wxGB_STATICBOXSIZER_H:
470 case wxGB_STATICBOXSIZER_V:
471 result = ParseStaticBoxSizer(buf, true);
472 break;
474 case wxGB_BOXSIZER_H:
475 case wxGB_BOXSIZER_V:
476 result = ParseStaticBoxSizer(buf, false);
477 break;
479 case wxGB_GRIDSIZER:
480 result = ParseGridSizer(buf, false);
481 break;
483 case wxGB_FLEXGRIDSIZER:
484 result = ParseGridSizer(buf, true);
485 break;
487 default:
488 result = -1;
489 break;
492 if(result < 0)
494 buf.Pop();
495 ::wxLogError(buf.GetAt() + wxT("Unknown type of sizer found!"));
496 return -1;
498 else
499 buf.Delegate();
501 return (int)buf.GetPos();
504 int wxGbSizerItem::ParseStaticBoxSizer(wxGbParseBuffer &buf, bool withlabel)
506 // skip sizer type
507 buf.PopChar();
509 // get title
510 if(withlabel && buf.PeekChar() == wxChar(wxGB_WND_LABEL_START))
512 wxString str;
513 if(buf.ToString(str))
514 m_caption = str;
515 else
517 wxLogError(buf.GetAt() + wxT("Error parsing label of static box sizer"));
518 return -1;
522 return ParseSizerContents(buf, wxGB_SIZER_BEGIN, wxGB_SIZER_END);
525 int wxGbSizerItem::ParseGridSizer(wxGbParseBuffer &buf, bool withgrow)
527 // skip sizer type
528 buf.PopChar();
530 // get columns / rows for this sizer
531 bool result = false;
532 buf.Push();
533 if(buf.PeekChar() == wxChar(wxGB_TUPLE_START))
535 buf.PopChar();
536 result = buf.ParseTuple(m_rows, m_cols);
538 while(result && withgrow)
540 // growable columns or rows
541 buf.EatWhites();
543 size_t val = 0;
544 wxChar type = buf.PeekChar();
546 if(type == wxChar(wxGB_GROW_ROW) ||
547 type == wxChar(wxGB_GROW_COL))
549 buf.PopChar();
551 // get number
552 size_t rowcol_idx, prop = 0;
553 result = buf.ToLong(rowcol_idx);
554 if(result)
556 // we got the number, now get proportion info (if needed)
557 if(buf.PeekChar() == wxChar(',') || buf.PeekChar() == wxChar(':'))
559 buf.PopChar();
560 result = buf.ToLong(prop);
562 else
563 break;
565 else
566 break;
568 if(result)
570 // we got all the stuff we need. Now check and add
571 wxSizerItemFlexInfo fi;
572 if(type == wxChar(wxGB_GROW_ROW))
573 fi.rowcol = 0;
574 else
575 fi.rowcol = 1;
577 // add proportion info
578 fi.idx = rowcol_idx;
579 fi.prop = prop;
581 // add this info
582 m_growinfo.push_back(fi);
585 else
586 break;
589 // get end tuple
590 result &= (buf.PeekChar() == wxChar(wxGB_TUPLE_END));
591 if(result)
592 buf.PopChar();
595 if(!result || (m_rows == 0 && m_cols == 0))
597 buf.Pop();
598 ::wxLogError(buf.GetAt() + wxT("Invalid or missing row / columns size for wx(flex)GridSizer"));
599 return -1;
602 buf.Delegate();
604 return ParseSizerContents(buf, wxGB_SIZER_BEGIN, wxGB_SIZER_END);
607 int wxGbSizerItem::ParseSizerContents(wxGbParseBuffer &buf, wxChar szbegin, wxChar szend)
609 // now get the sizer start and accumulate the items inside
610 if(buf.PeekChar() == szbegin)
612 buf.PopChar();
614 buf.Push();
615 if(ParseWindowControls(buf, szend) < 0)
617 buf.Pop();
618 ::wxLogError(buf.GetAt() + wxT("Error parsing sizer contents"));
619 return -1;
621 else
622 buf.Delegate();
624 buf.EatWhites();
626 else
628 ::wxLogError(buf.GetAt() + wxT("Expected begin sizer element '") +
629 wxString(szbegin) + wxT("'"));
630 return -1;
633 return buf.GetPos();
637 int wxGbSizerItem::ParseWindowControls(wxGbParseBuffer &buf, wxChar sizer_end)
639 // go into parse loop
640 while(1)
642 // ignore all whitespaces
643 buf.EatWhites();
645 // if we have a default window / sizer flag we will take that from
646 // here so all items in this sizer will get the default flags
647 if(buf.PeekChar() == wxChar(wxGB_DEFAULT_FLAGS))
649 buf.PopChar();
651 // check WHICH of the two we are supposed to make default
652 // if none matches, we do both
653 wxSizerFlags flags;
654 bool window = false, sizer = false;
655 if(buf.PeekChar() == wxChar('w'))
657 window = true;
658 flags = m_defWindowFlags;
659 buf.PopChar();
661 else if(buf.PeekChar() == wxChar('s'))
663 sizer = true;
664 flags = m_defSizerFlags;
665 buf.PopChar();
667 else
668 sizer = window = true; // no specification, both
670 wxString label;
671 if(ParseCommonFlags(buf, flags, label) != -1)
673 // apply the default flags
674 if(sizer)
675 m_defSizerFlags = flags;
676 if(window)
677 m_defWindowFlags = flags;
679 else
681 ::wxLogError(wxT("Error parsing default flags!"));
682 return -1;
685 buf.EatWhites();
688 // now parse items in between, see if this is a possible
689 // window, if so let's parse it
690 if(wxGbWindowItem::IsWindowQualifier(buf))
692 // store window item
693 //wxGbParseBuffer tmpbuf(buf);
694 buf.Push();
695 wxGbWindowItem *wi = new wxGbWindowItem(this, m_defWindowFlags,
696 m_defSizerFlags);
697 if(wi->Parse(buf) > 0)
699 // copy buffer back and store
700 buf.Delegate();
701 m_items.push_back(wi);
703 else
705 buf.Pop();
707 delete wi;
708 wxLogError(buf.GetAt() + wxT("Unable to parse window item"));
710 return -1;
713 else if(wxGbSizerItem::ScanSizerType(buf) != wxGB_UNDEFINED)
715 // if we have a sizer type here, that means
716 // we have to go recursive
717 //wxGbParseBuffer tmpbuf(buf);
718 buf.Push();
719 wxGbSizerItem *si = new wxGbSizerItem(this, m_defWindowFlags,
720 m_defSizerFlags);
721 if(si->Parse(buf) > 0)
723 // copy buffer back and store
724 buf.Delegate();
725 m_items.push_back(si);
727 else
729 buf.Pop();
731 delete si;
732 wxLogError(buf.GetAt() + wxT("Unable to parse sizer item"));
734 return -1;
737 else if(buf.PeekChar() == wxChar(sizer_end))
739 buf.PopChar();
741 // set default flags in m_flags for sizer
742 m_flags = m_defSizerFlags;
743 if(ParseCommonFlags(buf, m_flags, m_label) == -1)
744 return -1;
746 break;
748 else
750 if(buf.PeekChar() == wxChar(0))
751 wxLogError(buf.GetAt() + wxT("Reached premature EOF (no sizer end found)"));
752 else
753 wxLogError(buf.GetAt() + wxString::Format(wxT("Unknown item '%c' to parse"), buf.PeekChar()));
754 return -1;
758 return buf.GetPos();
761 bool wxGbSizerItem::Verify(wxGbBaseItem *item)
763 bool result = wxGbBaseItem::Verify(item);
765 if(item == NULL)
767 // self diagnostics
768 if(m_type == wxGB_UNDEFINED)
770 result = false;
771 ::wxLogError(wxT("No sizer type specified!"));
775 return result;
778 void wxGbSizerItem::AddToLookup(std::vector<wxGbBaseItem *> &list)
780 // push ourselves on it
781 list.push_back(this);
783 // go iterate our children
784 for(size_t i = 0; i < m_items.size(); i++)
785 m_items[i]->AddToLookup(list);
788 wxSizer *wxGbSizerItem::RealizeSizer(wxGuiBuilder &owner, wxWindow *parent)
790 // ok let's start with creating stuff
791 DoCreateSizer(parent);
793 // now go and add elements we have
794 if(m_sizer != NULL)
796 wxGbSizerItem *s;
797 wxGbWindowItem *w;
798 for(size_t i = 0; i < m_items.size(); i++)
800 // for other sizers, go and realize them
801 s = dynamic_cast<wxGbSizerItem *>(m_items[i]);
802 if(s != NULL)
804 wxSizer *sz = s->RealizeSizer(owner, parent);
805 if(sz == NULL)
806 SetRealizeError(owner);
808 wxCHECK_MSG(sz != NULL, m_sizer, wxT("Error realizing subsizer!"));
809 m_sizer->Add(sz, s->GetSizerFlags());
811 else
813 w = dynamic_cast<wxGbWindowItem *>(m_items[i]);
814 if(w != NULL)
816 if(w->GetWindowType() == wxGbWindowItem::WI_SPACER)
817 m_sizer->Add(w->GetWidth(), w->GetHeight(),
818 w->GetSizerFlags().GetProportion(),
819 w->GetSizerFlags().GetFlags(),
820 w->GetSizerFlags().GetBorderInPixels());
821 else
823 wxWindow *wnd = w->RealizeWindow(owner, parent);
824 if(wnd == NULL)
825 SetRealizeError(owner);
827 wxCHECK_MSG(wnd != NULL, m_sizer, wxT("Error creating window!"));
828 m_sizer->Add(wnd, w->GetSizerFlags());
835 return m_sizer;
838 void wxGbSizerItem::DoCreateSizer(wxWindow *parent)
840 // instantiate the type of sizer we need to create with the
841 // proper flags
842 m_sizer = NULL;
844 switch(m_type)
846 case wxGB_BOXSIZER_H:
847 m_sizer = new wxBoxSizer(wxHORIZONTAL);
848 break;
850 case wxGB_BOXSIZER_V:
851 m_sizer = new wxBoxSizer(wxVERTICAL);
852 break;
854 case wxGB_STATICBOXSIZER_H:
855 m_sizer = new wxStaticBoxSizer(wxHORIZONTAL, parent, m_caption);
856 break;
858 case wxGB_STATICBOXSIZER_V:
859 m_sizer = new wxStaticBoxSizer(wxVERTICAL, parent, m_caption);
860 break;
862 case wxGB_GRIDSIZER:
863 if(m_rows == 0 && m_cols > 0)
864 m_sizer = new wxGridSizer(m_cols);
865 else
866 m_sizer = new wxGridSizer(m_rows, m_cols, 0, 0);
867 break;
869 case wxGB_FLEXGRIDSIZER:
871 wxFlexGridSizer *f;
872 if(m_rows == 0 && m_cols > 0)
873 f = new wxFlexGridSizer(m_cols);
874 else
875 f = new wxFlexGridSizer(m_rows, m_cols, 0, 0);
877 m_sizer = f;
879 // add the columns and rows to grow
880 for(size_t i = 0; i < m_growinfo.size(); i++)
882 if(!m_growinfo[i].rowcol)
883 f->AddGrowableRow(m_growinfo[i].idx, m_growinfo[i].prop);
884 else
885 f->AddGrowableCol(m_growinfo[i].idx, m_growinfo[i].prop);
888 break;
890 default:
891 break;
895 //----------------------------------------------------------------------
896 // wxGbWindowItem
897 //----------------------------------------------------------------------
899 int wxGbWindowItem::Parse(wxGbParseBuffer &buf)
901 int result = 0;
903 // skip whitespaces
904 buf.EatWhites();
906 int kind = 0;
907 while(result == 0)
909 //wxGbParseBuffer tb(buf);
910 buf.Push();
911 switch(kind)
913 // attempt a subst window item
914 case 0:
915 result = ParseSubstitute(buf);
916 break;
917 case 1:
918 result = ParseStaticText(buf);
919 break;
920 case 2:
921 result = ParsePanel(buf);
922 break;
923 case 3:
924 result = ParseButton(buf);
925 break;
926 case 4:
927 result = ParseRadioButton(buf);
928 break;
929 case 5:
930 result = ParseCheckBox(buf);
931 break;
932 case 6:
933 result = ParseTextCtrl(buf);
934 break;
935 case 7:
936 result = ParseSpecial(buf);
937 break;
938 case 8:
939 result = ParseTabsheet(buf);
940 break;
941 default:
942 result = -1;
943 break;
946 // when we are lucky
947 if(result > 0)
949 buf.Delegate();
951 // parse common flags
952 m_flags = m_defWindowFlags;
953 if(ParseCommonFlags(buf, m_flags, m_label) == -1)
954 return -1;
956 return (int)buf.GetPos();
958 else
960 buf.Pop();
961 kind++;
965 return -1;
968 bool wxGbWindowItem::IsWindowQualifier(const wxGbParseBuffer &buf)
970 char chr = (char)buf.PeekChar();
972 return (chr == wxGB_WND_SUBSTITUTE) ||
973 (chr == wxGB_WND_CHECK_START) ||
974 (chr == wxGB_WND_RADIO_START) ||
975 (chr == wxGB_WND_BUTTON_START) ||
976 (chr == wxGB_WND_SPECIAL_START) ||
977 //(chr == wxGB_WND_TEXTCTL_START) ||
978 //(chr == wxGB_WND_CHOICE_START) ||
979 //(chr == wxGB_WND_COMBO_START) ||
980 //(chr == wxGB_WND_LISTCTRL_START) ||
981 //(chr == wxGB_WND_TREECTRL_START) ||
982 (chr == wxGB_TABSHEET_START) ||
983 (chr == wxGB_WND_LABEL_START) ||
984 (chr == wxGB_PANEL_ITEM);
987 int wxGbWindowItem::ParseSubstitute(wxGbParseBuffer &buf)
989 size_t nr;
991 ResetType();
993 // verify if we are parsing the right thing
994 if(buf.PeekChar() == wxChar(wxGB_WND_SUBSTITUTE))
996 // remove subst marker
997 buf.PopChar();
999 // get number
1000 if(buf.ToLong(nr))
1002 m_number = nr;
1004 // set type
1005 m_windowType = WI_SUBSTITUTE;
1007 else
1009 ::wxLogError(buf.GetAt() + wxT("Error while parsing substitute number"));
1010 return -1;
1013 else
1014 return 0; // no scan
1016 return buf.GetPos();
1019 int wxGbWindowItem::ParseStaticText(wxGbParseBuffer &buf)
1021 ResetType();
1023 // verify if we are parsing the right thing
1024 if(buf.PeekChar() == wxChar(wxGB_WND_LABEL_START))
1026 wxString strval;
1028 // get string
1029 if(buf.ToString(strval))
1031 m_caption = strval;
1033 m_windowType = WI_STATICTEXT;
1035 else
1037 ::wxLogError(buf.GetAt() + wxT("Error while parsing static text label"));
1038 return -1;
1041 else
1042 return 0; // no scan
1044 return buf.GetPos();
1047 int wxGbWindowItem::ParseButton(wxGbParseBuffer &buf)
1049 static gb_button_ids gb_ids[] = { { wxT("OK"), wxID_OK }, { wxT("CANCEL"), wxID_CANCEL },
1050 { wxT("APPLY"), wxID_APPLY }, { wxT("YES"), wxID_YES },
1051 { wxT("NO"), wxID_NO }, { wxT("STATIC"), wxID_STATIC },
1052 { wxT("FORWARD"), wxID_FORWARD }, { wxT("BACKWARD"), wxID_BACKWARD },
1053 { wxT("DEFAULT"), wxID_DEFAULT }, { wxT("MORE"), wxID_MORE },
1054 { wxT("SETUP"), wxID_SETUP }, { wxT("RESET"), wxID_RESET },
1055 { wxT("CONTEXTHELP"), wxID_CONTEXT_HELP }, { wxT("YESTOALL"), wxID_YESTOALL },
1056 { wxT("NOTOALL"), wxID_NOTOALL }, { wxT("ABORT"), wxID_ABORT },
1057 { wxT("RETRY"), wxID_RETRY }, { wxT("IGNORE"), wxID_IGNORE },
1058 { wxT("ADD"), wxID_ADD }, { wxT("REMOVE"), wxID_REMOVE },
1059 { wxT("UP"), wxID_UP }, { wxT("DOWN"), wxID_DOWN },
1060 { wxT("HOME"), wxID_HOME }, { wxT("REFRESH"), wxID_REFRESH },
1061 { wxT("STOP"), wxID_STOP }, { wxT("INDEX"), wxID_INDEX },
1062 { wxT(""), wxID_ANY } }; /* keep this last! */
1065 ResetType();
1067 // verify if we are parsing the right thing
1068 if(buf.PeekChar() == wxChar(wxGB_WND_BUTTON_START))
1070 // get button start
1071 buf.PopChar();
1073 bool valid_button = false;
1074 if(buf.PeekChar() == wxChar(wxGB_WND_AUTOID_START))
1076 // we are going to auto ID first, which means the id of the button
1077 // will be defaulted to a standard ID based upon a match
1078 buf.PopChar();
1080 buf.Push();
1081 wxString ourlabel;
1082 while(buf.PeekChar() != wxChar(0) && buf.PeekChar() != wxChar(wxGB_WND_AUTOID_END))
1083 ourlabel.Append(buf.PopChar());
1085 if(buf.PeekChar() == wxChar(wxGB_WND_AUTOID_END))
1087 buf.Delegate();
1088 buf.PopChar();
1090 // check which face we have
1091 size_t pos = 0;
1092 while(gb_ids[pos].id != wxID_ANY)
1094 if(ourlabel.IsSameAs(gb_ids[pos].title, false))
1096 m_id = gb_ids[pos].id;
1097 break;
1099 pos++;
1102 if(gb_ids[pos].id == wxID_ANY)
1104 ::wxLogError(buf.GetAt() + wxT("Unknown auto ID for button!"));
1105 return -1;
1108 // check for semicolon, we skip that for a label
1109 // we can do without, but it looks nicer
1110 if(buf.PeekChar() == wxChar(wxGB_LABEL_MARK))
1111 buf.PopChar();
1113 valid_button = true;
1115 else
1117 buf.Pop();
1118 ::wxLogError(buf.GetAt() + wxT("Premature end for button auto ID (missing end marker)"));
1119 return -1;
1124 if(buf.PeekChar() == wxChar(wxGB_WND_LABEL_START))
1126 // get string
1127 wxString strval;
1128 if(buf.ToString(strval))
1129 m_caption = strval;
1130 else
1132 ::wxLogError(buf.GetAt() + wxT("Error while parsing button text"));
1133 return -1;
1136 valid_button = true;
1139 // parse the end of the button
1140 if(valid_button)
1142 // end button marker
1143 if(buf.PeekChar() == wxChar(wxGB_WND_BUTTON_END))
1145 // remove end marker
1146 buf.PopChar();
1148 m_windowType = WI_BUTTON;
1151 else
1152 return 0;
1154 else
1155 return 0; // no scan
1157 return buf.GetPos();
1160 int wxGbWindowItem::ParseTabsheet(wxGbParseBuffer &buf)
1162 ResetType();
1164 wxGbWindowItem *wi;
1165 if(buf.PeekChar(0) == wxChar(wxGB_TABSHEET_START) &&
1166 buf.PeekChar(1) == wxChar(wxGB_SIZER_BEGIN))
1168 // let's go parse
1169 buf.PopChar(2);
1171 while(1)
1173 // in a while loop we allow only panel items which will
1174 // become the base of the sizer
1175 buf.EatWhites();
1177 // scan for panel
1178 if(buf.PeekChar() == wxChar(wxGB_PANEL_ITEM))
1180 // create a new window item and attempt
1181 // a parse
1182 wi = new wxGbWindowItem(0, m_defWindowFlags, m_defSizerFlags);
1183 buf.Push();
1184 if(wi->Parse(buf) > 0)
1186 // add to our collection
1187 buf.Delegate();
1188 m_windowItems.push_back(wi);
1190 // if no tab name is given, force a title
1191 if(wi->m_caption.IsEmpty())
1192 wi->m_caption = wxString::Format(wxT("Tab %i"), (int)m_windowItems.size());
1194 else
1196 delete wi;
1197 buf.Pop();
1199 ::wxLogError(buf.GetAt() + wxT("Error while parsing tabsheet item"));
1200 return -1;
1204 else if(buf.PeekChar() == wxChar(wxGB_SIZER_END))
1206 // end of the panel
1207 buf.PopChar();
1208 m_windowType = WI_TABSHEET;
1210 return buf.GetPos();
1212 else
1214 ::wxLogError(buf.GetAt() + wxT("Only panel items allowed in a wxNotebook item"));
1215 return -1;
1220 return 0;
1223 int wxGbWindowItem::ParseTextCtrl(wxGbParseBuffer &buf)
1225 ResetType();
1227 // verify if we are parsing the right thing
1228 if(buf.PeekChar() == wxChar(wxGB_WND_TEXTCTL_START))
1230 // get start
1231 buf.PopChar();
1233 // check if we are multi or single line
1234 wxChar chr = buf.PeekChar();
1235 if(chr == wxChar(wxGB_WND_TEXTCTL_SINGLE) ||
1236 chr == wxChar(wxGB_WND_TEXTCTL_MULTI))
1238 // set flag for text ctrl type
1239 m_multiLine = (chr == wxChar(wxGB_WND_TEXTCTL_MULTI));
1241 m_windowType = WI_TEXT;
1243 // now scan until all -- or == chars are gone
1244 while(buf.PeekChar() == chr)
1245 buf.PopChar();
1247 // multi line label scanning (or simply appending multiple
1248 // text blocks to one, since they are encapsulated in a text ctrl
1249 bool labelscanning = true;
1250 while(labelscanning)
1252 // if we have a label, scan this one
1253 buf.EatWhites();
1254 if(buf.PeekChar() == wxChar(wxGB_WND_LABEL_START))
1256 // get string
1257 wxString strval;
1258 if(buf.ToString(strval))
1260 if(m_multiLine && !m_caption.IsEmpty())
1261 m_caption << wxT("\n");
1262 m_caption << strval;
1264 else
1266 ::wxLogError(buf.GetAt() + wxT("Error while parsing text"));
1267 return -1;
1270 else
1271 labelscanning = false;
1274 // now scan until all -- or == chars are gone
1275 // they must match, to enforce the multi or single line text
1276 while(buf.PeekChar() == chr)
1277 buf.PopChar();
1279 // end button marker
1280 if(buf.PeekChar() == wxChar(wxGB_WND_TEXTCTL_END))
1281 buf.PopChar();
1282 else
1284 ::wxLogError(buf.GetAt() + wxT("End of text ctrl element expected"));
1285 return -1;
1288 else
1289 return 0; // no match
1291 else
1292 return 0; // no scan
1294 return buf.GetPos();
1297 int wxGbWindowItem::ParseSpecial(wxGbParseBuffer &buf)
1299 ResetType();
1301 // verify if we are parsing the right thing
1302 if(buf.PeekChar() == wxChar(wxGB_WND_SPECIAL_START))
1304 // get start
1305 buf.PopChar();
1307 wxString label;
1308 if(buf.ToLabel(label))
1310 if(label.IsSameAs(wxT("hdiv")))
1311 m_windowType = WI_LINE_H;
1312 else if(label.IsSameAs(wxT("vdiv")))
1313 m_windowType = WI_LINE_V;
1314 else if(label.IsSameAs(wxT("spc")))
1316 m_windowType = WI_SPACER;
1318 // we can expect a semi colon and one or two values. One value
1319 // means the width and height are the same, two values means
1320 // seperate values
1321 if(buf.PeekChar() == wxChar(wxGB_LABEL_MARK))
1323 buf.PopChar();
1324 int width = -1, height = -1;
1326 if(buf.ParseTuple(width, height))
1328 // only assign when we have at least a valid value
1329 if(width != -1 && height != -1)
1331 m_height = height;
1332 m_width = width;
1334 else if(width != -1)
1335 m_height = m_width = width;
1337 else
1339 ::wxLogError(buf.GetAt() + wxT("Error parsing spacer width / height values!"));
1340 return -1;
1345 if(buf.PeekChar() != wxChar(wxGB_WND_SPECIAL_END))
1346 return 0;
1348 buf.PopChar();
1351 else
1352 return 0;
1354 else
1355 return 0; // no scan
1357 return buf.GetPos();
1360 int wxGbWindowItem::ParseRadioButton(wxGbParseBuffer &buf)
1362 ResetType();
1364 // verify if we are parsing the right thing
1365 if(buf.PeekChar() == wxChar(wxGB_WND_RADIO_START))
1367 // get radio start
1368 buf.PopChar();
1370 // get a space or a '.' or '*' for default checked state
1371 wxChar chr = buf.PeekChar();
1372 if(chr == wxChar(' ') || chr == wxChar('.') || chr == wxChar('*'))
1374 // get entry
1375 buf.PopChar();
1377 // checked state all but space
1378 m_checked = !(chr == wxChar(' '));
1380 // see if we have a ending radio
1381 if(buf.PeekChar() != wxChar(wxGB_WND_RADIO_END))
1382 return 0; // nope still not enough
1384 // now we have enough
1385 buf.PopChar();
1386 m_windowType = WI_RADIO;
1388 buf.EatWhites();
1390 // check for a caption. This is optional
1391 if(buf.PeekChar() == wxChar(wxGB_WND_LABEL_START))
1393 // get string
1394 wxString strval;
1395 if(buf.ToString(strval))
1396 m_caption = strval;
1397 else
1399 ::wxLogError(buf.GetAt() + wxT("Error while parsing checkbox text"));
1400 return -1;
1404 else
1405 return 0; // probably not what we need
1407 else
1408 return 0; // no scan
1410 return buf.GetPos();
1413 int wxGbWindowItem::ParseCheckBox(wxGbParseBuffer &buf)
1415 ResetType();
1417 // verify if we are parsing the right thing
1418 if(buf.PeekChar() == wxChar(wxGB_WND_CHECK_START))
1420 // get check start
1421 buf.PopChar();
1423 // get a space or a 'x' or 'X' for default checked state
1424 wxChar chr = buf.PeekChar();
1425 if(chr == wxChar(' ') || chr == wxChar('x') || chr == wxChar('X'))
1427 // get entry
1428 buf.PopChar();
1430 // checked state all but space
1431 m_checked = !(chr == wxChar(' '));
1433 // see if we have a ending radio
1434 if(buf.PeekChar() != wxChar(wxGB_WND_CHECK_END))
1435 return 0; // nope still not enough
1437 // now we have enough
1438 buf.PopChar();
1439 m_windowType = WI_CHECK;
1441 buf.EatWhites();
1443 // check for a caption. This is optional
1444 if(buf.PeekChar() == wxChar(wxGB_WND_LABEL_START))
1446 // get string
1447 wxString strval;
1448 if(buf.ToString(strval))
1449 m_caption = strval;
1450 else
1452 ::wxLogError(buf.GetAt() + wxT("Error while parsing checkbox text"));
1453 return -1;
1457 else
1458 return 0; // probably not what we need
1460 else
1461 return 0; // no scan
1463 return buf.GetPos();
1466 int wxGbWindowItem::ParsePanel(wxGbParseBuffer &buf)
1468 ResetType();
1470 // verify if we are parsing the right thing
1471 if(buf.PeekChar() == wxChar(wxGB_PANEL_ITEM))
1473 // skip panel element
1474 buf.PopChar();
1476 // if we have a label, parse this first
1477 if(buf.PeekChar() == wxChar(wxGB_WND_LABEL_START))
1479 wxString label;
1480 if(buf.ToString(label))
1481 m_caption = label;
1482 else
1483 return 0; // no panel
1486 // ok it is a panel, get common flags
1487 // and parse the assigned sizer
1488 m_flags = m_defWindowFlags;
1489 if(ParseCommonFlags(buf, m_flags, m_label) == -1)
1490 return -1;
1492 // set the type
1493 m_windowType = WI_PANEL;
1495 // get the assign char
1496 if(buf.PeekChar() == wxGB_ASSIGN)
1498 // now set the type and assign the sizer
1499 buf.PopChar();
1501 if(wxGbSizerItem::ScanSizerType(buf) != wxGB_UNDEFINED)
1503 // if we have a sizer type here, that means
1504 // we have to go recursive
1505 //wxGbParseBuffer tmpbuf(buf);
1506 buf.Push();
1507 wxGbSizerItem *si = new wxGbSizerItem(GetParent(),
1508 m_defWindowFlags,
1509 m_defSizerFlags);
1511 if(si->Parse(buf) > 0)
1513 // copy buffer back and store
1514 buf.Delegate();
1515 m_sizer = si;
1517 else
1519 buf.Pop();
1521 delete si;
1522 wxLogError(buf.GetAt() + wxT("Unable to parse and assign sizer item"));
1524 return -1;
1529 else
1530 return 0; // no match
1532 return buf.GetPos();
1536 void wxGbWindowItem::AddToLookup(std::vector<wxGbBaseItem *> &list)
1538 // push ourselves on it
1539 list.push_back(this);
1541 // if this window has a sizer as well, go recursive from there
1542 if(m_sizer != NULL)
1543 m_sizer->AddToLookup(list);
1545 // if we have more window items
1546 for(size_t i = 0; i < m_windowItems.size(); i++)
1547 m_windowItems[i]->AddToLookup(list);
1550 bool wxGbWindowItem::Verify(wxGbBaseItem *item)
1552 bool result = wxGbBaseItem::Verify(item);
1554 if(item == NULL)
1556 // self diagnostics
1557 if(m_windowType == WI_UNKNOWN)
1559 result = false;
1560 ::wxLogError(wxT("No window type specified!"));
1563 // if we have a substituted window, but no assignee
1564 // then we have a problem
1565 if(m_windowType == WI_SUBSTITUTE)
1567 if(m_number == 0)
1569 result = false;
1570 ::wxLogError(wxT("No substitute number found!"));
1572 else if(m_wnd == NULL)
1574 result = false;
1575 ::wxLogError(wxString::Format(wxT("No assigned window for element $%i"), m_number));
1579 else
1581 wxGbWindowItem *w = dynamic_cast<wxGbWindowItem *>(item);
1582 if(w != NULL)
1584 // if both windows are substitutes, then we check if they are cross defined
1585 if(w->GetWindowType() == WI_SUBSTITUTE && m_windowType == WI_SUBSTITUTE)
1587 if(w->GetNumber() == m_number)
1589 result = false;
1590 ::wxLogError(wxString::Format(wxT("Substitute element $%i is defined more then once!"),
1591 m_number));
1597 return result;
1600 wxWindow *wxGbWindowItem::RealizeWindow(wxGuiBuilder &owner, wxWindow *parent)
1602 // if we have an assigned window, we are done easily
1603 if(m_windowType == WI_SUBSTITUTE)
1605 wxCHECK_MSG(m_wnd != NULL, NULL, wxT("Assigned window is not present!"));
1607 // see if we need to reparent the window this is needed for example
1608 // when controls are created in a wxPanel for a wxNotebook etc, like;
1609 // #=H{ $1 $2 $3}
1610 if(m_wnd->GetParent() != parent)
1611 m_wnd->Reparent(parent);
1613 return m_wnd;
1615 else
1617 // we are supposed to create one of our own
1618 DoCreateWindow(owner, parent);
1619 if(m_wnd == NULL)
1620 SetRealizeError(owner);
1622 wxCHECK_MSG(m_wnd != 0, NULL, wxT("Error creating window item!"));
1624 // now, if we are a panel, and we have an assigned sizer,
1625 // go and realize a sizer for this window too
1626 if(m_windowType == WI_PANEL)
1628 wxPanel *p = wxDynamicCast(m_wnd, wxPanel);
1629 if(p != NULL && m_sizer != NULL)
1631 // ok, now realize the sizer with the panel as new parent
1632 wxSizer *sz = m_sizer->RealizeSizer(owner, p);
1633 if(sz == NULL)
1634 SetRealizeError(owner);
1636 // assign sizer to panel
1637 wxCHECK_MSG(sz != NULL, m_wnd, wxT("Error creating wxPanel->wxSizer!"));
1638 p->SetSizer(sz);
1641 #ifndef __SMARTPHONE__
1642 else if(m_windowType == WI_TABSHEET)
1644 wxNotebook *n = wxDynamicCast(m_wnd, wxNotebook);
1645 if(n != NULL && m_windowItems.size() > 0)
1647 for(size_t i = 0; i < m_windowItems.size(); i++)
1649 // now realize all windows that we refer
1650 wxWindow *w = m_windowItems[i]->RealizeWindow(owner, n);
1651 wxCHECK_MSG(w != NULL, m_wnd, wxT("Error creating wxNotebook item"));
1653 // add this as a page
1654 n->AddPage(w, m_windowItems[i]->GetCaption());
1658 #endif
1661 return m_wnd;
1664 void wxGbWindowItem::DoCreateWindow(wxGuiBuilder &owner, wxWindow *parent)
1666 // maintain assigned window
1667 if(m_windowType == WI_SUBSTITUTE)
1668 return;
1670 m_wnd = NULL;
1672 // get the ID, leave assigned one if there
1673 if(m_id == wxID_ANY)
1674 m_id = owner.RequestID(GetLabel());
1676 // get the size and the style of the window to create
1677 // if they do not exist, they are left default
1678 wxSize size = wxDefaultSize;
1679 long style = 0;
1681 bool gotstyle = owner.RequestWindowParams(GetLabel(), style, size);
1682 gotstyle &= (style != 0);
1684 // we create a window with the default style, or the style given by the
1685 // registered item. If that style is also zero, the default style is taken
1686 // again.
1687 // TODO: What happens when the user explicitly wants a style of zero? If
1688 // it is set to zero, the default style is taken again.
1689 switch(m_windowType)
1691 case WI_PANEL:
1692 if(!gotstyle)
1693 m_wnd = new wxPanel(parent, m_id, wxDefaultPosition, size);
1694 else
1695 m_wnd = new wxPanel(parent, m_id, wxDefaultPosition, size, style);
1696 break;
1698 case WI_STATICTEXT:
1699 if(!gotstyle)
1700 m_wnd = new wxStaticText(parent, m_id, m_caption, wxDefaultPosition, size);
1701 else
1702 m_wnd = new wxStaticText(parent, m_id, m_caption, wxDefaultPosition, size, style);
1703 break;
1705 case WI_BUTTON:
1706 if(!gotstyle)
1707 m_wnd = new wxButton(parent, m_id, m_caption, wxDefaultPosition, size);
1708 else
1709 m_wnd = new wxButton(parent, m_id, m_caption, wxDefaultPosition, size, style);
1710 break;
1712 case WI_RADIO:
1714 wxRadioButton *r;
1715 if(!gotstyle)
1716 r = new wxRadioButton(parent, m_id, m_caption, wxDefaultPosition, size);
1717 else
1718 r = new wxRadioButton(parent, m_id, m_caption, wxDefaultPosition, size, style);
1720 r->SetValue(m_checked);
1721 m_wnd = r;
1723 break;
1725 case WI_CHECK:
1727 wxCheckBox *c;
1728 if(!gotstyle)
1729 c = new wxCheckBox(parent, m_id, m_caption, wxDefaultPosition, size);
1730 else
1731 c = new wxCheckBox(parent, m_id, m_caption, wxDefaultPosition, size, style);
1733 c->SetValue(m_checked);
1734 m_wnd = c;
1736 break;
1738 case WI_TEXT:
1739 if(!gotstyle)
1740 m_wnd = new wxTextCtrl(parent, m_id, m_caption, wxDefaultPosition,
1741 size, ~wxTE_PROCESS_ENTER & (m_multiLine ? wxTE_MULTILINE : 0));
1742 else
1743 m_wnd = new wxTextCtrl(parent, m_id, m_caption, wxDefaultPosition,
1744 size, ~wxTE_PROCESS_ENTER & (style | (m_multiLine ? wxTE_MULTILINE : 0)));
1745 break;
1747 case WI_LINE_H:
1748 case WI_LINE_V:
1749 m_wnd = new wxStaticLine(parent, m_id, wxDefaultPosition, wxDefaultSize,
1750 (m_windowType == WI_LINE_H ? wxLI_HORIZONTAL : wxLI_VERTICAL));
1751 break;
1752 #ifndef __SMARTPHONE__
1753 case WI_TABSHEET:
1754 if(!gotstyle)
1755 m_wnd = new wxNotebook(parent, m_id, wxDefaultPosition, size);
1756 else
1757 m_wnd = new wxNotebook(parent, m_id, wxDefaultPosition, size, style);
1758 break;
1759 #endif
1760 default:
1761 break;
1765 //----------------------------------------------------------------------
1766 // wxGuiBuilder
1767 //----------------------------------------------------------------------
1769 bool wxGuiBuilder::Build(wxWindow *parent, int startID, bool recompile)
1771 m_realizeError = false;
1772 m_workID = startID;
1773 m_sizer = NULL;
1775 // we need to have a parent window to assign our
1776 // controls to
1777 if(parent == NULL)
1779 ::wxLogError(wxT("Please assign a topwindow"));
1780 return 0;
1783 // recompile the structure
1784 if(m_topSizer == NULL || recompile)
1786 if(!Compile())
1787 return 0;
1790 if(m_topSizer != NULL)
1792 // set up relations for quick lookup
1793 m_lookup.clear();
1794 FillLookupList(m_topSizer);
1796 // if we are in demo mode, we substitute all windows ourselves
1797 if(m_demoMode)
1798 DoDemoMode(parent);
1799 else
1801 // fill all substitutes, if we have ID's that are not filled
1802 // the verification phase will nag us about it
1803 wxGbWindowStub *st;
1804 wxGbWindowItem *w;
1805 for(size_t i = 0; i < m_regitems.size(); i++)
1807 st = dynamic_cast<wxGbWindowStub *>(m_regitems[i]);
1808 if(st != NULL)
1810 for(size_t n = 0; n < m_lookup.size(); n++)
1812 w = dynamic_cast<wxGbWindowItem *>(m_lookup[n]);
1813 if(w != NULL)
1815 if((size_t)st->GetId() == w->GetNumber() &&
1816 w->GetWindowType() == wxGbWindowItem::WI_SUBSTITUTE)
1818 w->AssignWindow(st->GetWindow());
1819 break;
1827 // verify double entries, valid entries etc
1828 if(!VerifyLookupList())
1830 // delete all and give error
1831 ::wxLogError(wxT("Verification error(s) encountered"));
1832 Reset();
1833 return 0;
1836 // let's start the show
1837 m_sizer = m_topSizer->RealizeSizer((*this), parent);
1838 if(m_sizer == NULL)
1840 ::wxLogError(wxT("Error realizing sizer structure"));
1841 Reset();
1842 return 0;
1844 else
1846 if(m_realizeError)
1847 ::wxLogError(wxT("Not all elements have been created succesfully"));
1851 else
1852 ::wxLogError(wxT("Cannot realize sizer, no topsizer window"));
1854 // map our controls, this will abort when one or
1855 // more cannot be mapped
1856 if(m_sizer != NULL)
1858 MapControlPointers();
1859 return true;
1862 return false;
1865 void wxGuiBuilder::DoDemoMode(wxWindow *parent)
1867 wxGbWindowItem *w;
1868 for(size_t n = 0; n < m_lookup.size(); n++)
1870 w = dynamic_cast<wxGbWindowItem *>(m_lookup[n]);
1871 if(w != NULL)
1873 if(w->GetWindowType() == wxGbWindowItem::WI_SUBSTITUTE)
1875 wxPanel *pnl = new wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER);
1876 new wxStaticText(pnl, -1, wxString::Format(wxT(" $%i"), w->GetNumber()));
1878 w->AssignWindow(pnl);
1884 bool wxGuiBuilder::Compile()
1886 wxGbParseBuffer pb(m_buffer);
1888 // setup a parse buffer
1889 Reset();
1891 // seek for a start sizer entry
1892 pb.EatWhites();
1894 // create a sizer and set some defaults
1895 // this is only useful once at the beginning
1896 m_topSizer = new wxGbSizerItem(0, m_defWindowFlags,
1897 m_defSizerFlags);
1899 // go parsing
1900 //wxGbParseBuffer tmpbuf(m_buffer);
1901 pb.Push();
1902 if(m_topSizer->Parse(pb) > 0)
1904 // write state of buffer back maybe for
1905 // last position in string, and chained sizers
1907 else
1909 ::wxLogError(pb.GetAt() + wxT("Error parsing the top sizer"));
1910 Reset();
1912 return false;
1915 pb.Pop();
1916 return true;
1919 void wxGuiBuilder::FillLookupList(wxGbSizerItem *si)
1921 if(si != NULL)
1922 si->AddToLookup(m_lookup);
1925 bool wxGuiBuilder::VerifyLookupList()
1927 bool status = true;
1929 if(m_lookup.size() < 2)
1931 ::wxLogError(wxT("There are not enough window items or sizers to realize!"));
1932 return false;
1935 // check for element problems
1936 for(size_t i = 0; i < m_lookup.size(); i++)
1938 // perform verification on item, and remember false status
1939 status &= m_lookup[i]->Verify(NULL);
1941 // if we have errors, do not bother with
1942 // more errors, as the element is not ok to begin with
1943 if(!status)
1944 continue;
1946 for(size_t n = 0; n < m_lookup.size(); n++)
1948 // ignore ourselves, and cross compare items
1949 if(i != n)
1950 status &= m_lookup[i]->Verify(m_lookup[n]);
1954 return status;
1957 // method that returns a new ID to be used. If the work ID is wxID_ANY
1958 // we define one ourselves, if the ID has another value, we return and
1959 // increment
1960 long wxGuiBuilder::RequestID(const wxString &label)
1962 if(!label.IsEmpty())
1964 // get label from our registered item list
1965 // if the label is found and the id is not wxID_ANY
1966 for(size_t i = 0; i < m_regitems.size(); i++)
1968 if(m_regitems[i]->GetLabel().IsSameAs(label))
1970 // found, now return in case it is a valid ID
1971 if(m_regitems[i]->GetId() != wxID_ANY)
1972 return m_regitems[i]->GetId();
1977 // if we come here there was no predefined label
1978 // and we either create a new one, or iterate a work ID
1979 long value;
1980 if(m_workID == wxID_ANY)
1981 value = wxNewId();
1982 else
1984 value = m_workID;
1985 m_workID++;
1988 return value;
1991 bool wxGuiBuilder::RequestWindowParams(const wxString &label, long &style, wxSize &size)
1993 if(!label.IsEmpty())
1995 // get label from our registered item list
1996 // if the label is found and the id is not wxID_ANY
1997 for(size_t i = 0; i < m_regitems.size(); i++)
1999 if(m_regitems[i]->GetLabel().IsSameAs(label))
2001 style = m_regitems[i]->GetStyle();
2002 size = m_regitems[i]->GetSize();
2003 return true;
2008 return false;
2011 wxGbWindowItem *wxGuiBuilder::DoFindWindowByLabel(const wxString &label)
2013 wxGbWindowItem *w;
2014 for(size_t i = 0; i < m_lookup.size(); i++)
2016 if(m_lookup[i]->GetLabel().IsSameAs(label))
2018 w = dynamic_cast<wxGbWindowItem *>(m_lookup[i]);
2019 if(w != NULL)
2020 return w;
2024 return NULL;
2027 void wxGuiBuilder::Reset()
2029 m_lookup.clear();
2030 m_lastIndex = 1;
2032 if(m_topSizer != NULL)
2034 delete m_topSizer;
2035 m_topSizer = 0;
2039 bool wxGuiBuilder::CanRegister(const wxGbRegWindowBase &item)
2041 const wxGbWindowStub *st = dynamic_cast<const wxGbWindowStub *>(&item);
2042 if(st != NULL)
2044 if(st->GetId() < 1)
2046 ::wxLogError(wxT("Illegal stub ID!"));
2047 return false;
2050 else if(item.GetLabel().IsEmpty())
2052 ::wxLogError(wxT("Label is missing, no registering possible!"));
2053 return false;
2056 wxGbWindowStub *tt;
2057 for(size_t i = 0; i < m_regitems.size(); i++)
2059 if(st != NULL)
2061 // if we have a stub, check for existence
2062 tt = dynamic_cast<wxGbWindowStub *>(m_regitems[i]);
2063 if(tt != NULL)
2065 if(tt->GetId() == st->GetId())
2067 ::wxLogError(wxT("Stub window ID already registered!"));
2068 return false;
2072 else if(m_regitems[i]->GetLabel().IsSameAs(item.GetLabel()))
2074 ::wxLogError(wxT("Label '") + item.GetLabel() + wxT("' already registered!"));
2075 return false;
2079 return true;
2082 void wxGuiBuilder::MapControlPointers()
2084 wxString str;
2086 wxGbWindowItem *w;
2087 for(size_t i = 0; i < m_regitems.size(); i++)
2089 w = DoFindWindowByLabel(m_regitems[i]->GetLabel());
2090 if(w)
2092 if(!m_regitems[i]->SetPointer(w))
2094 if(!str.IsEmpty())
2095 str << wxT("\n");
2097 str << wxT("Unable to set pointer reference for label '")
2098 << m_regitems[i]->GetLabel() << wxT("'");
2101 else
2103 if(!str.IsEmpty())
2104 str << wxT("\n");
2106 str << wxT("Registered label '") << m_regitems[i]->GetLabel()
2107 << wxT("' did not reference any control!");
2111 // if we have fatal errors, show user and give the possibility to abort
2112 if(!str.IsEmpty())
2114 wxString msg = wxT("Not all window pointers can be assigned! The program\n"
2115 "will most likely become unstable if you continue. \n"
2116 "Would you like to abort the application?\n\n") + str;
2117 int res = ::wxMessageBox(msg, wxT("Fatal errors!"), wxICON_HAND | wxYES_NO);
2118 if(res == wxYES)
2119 ::wxLogFatalError(str);