]> git.saurik.com Git - wxWidgets.git/blame - utils/dialoged/src/reseditr.cpp
GetItem() now works (it was completely broken)
[wxWidgets.git] / utils / dialoged / src / reseditr.cpp
CommitLineData
457814b5
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: reseditr.cpp
3// Purpose: Resource editor class
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "reseditr.h"
14#endif
15
16// For compilers that support precompilation, includes "wx/wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx/wx.h"
25
26#include "wx/checkbox.h"
27#include "wx/button.h"
28#include "wx/choice.h"
29#include "wx/listbox.h"
30#include "wx/radiobox.h"
31#include "wx/statbox.h"
32#include "wx/gauge.h"
33#include "wx/slider.h"
34#include "wx/textctrl.h"
b127f301
RR
35#include "wx/menu.h"
36#include "wx/toolbar.h"
457814b5
JS
37#endif
38
39#include "wx/scrolbar.h"
40
41#include <ctype.h>
42#include <stdlib.h>
43#include <math.h>
44#include <string.h>
45
2049ba38 46#if defined(__WXMSW__) && !defined(__GNUWIN32__)
457814b5
JS
47#include <strstrea.h>
48#else
49#include <strstream.h>
50#endif
51
2049ba38 52#ifdef __WXMSW__
457814b5
JS
53#include <windows.h>
54#endif
55
d0fff5cb 56#ifdef __WXMSW__
457814b5 57#include "wx/help.h"
b127f301 58#endif
457814b5
JS
59
60#include "reseditr.h"
61#include "winprop.h"
457814b5 62#include "dlghndlr.h"
ae8351fc
JS
63#include "edtree.h"
64#include "edlist.h"
457814b5
JS
65
66static void ObjectMenuProc(wxMenu& menu, wxCommandEvent& event);
ae8351fc 67wxResourceManager *wxResourceManager::sm_currentResourceManager = NULL;
457814b5 68
b127f301
RR
69#ifdef __WXGTK__
70#include "bitmaps/load.xpm"
71#include "bitmaps/save.xpm"
72#include "bitmaps/new.xpm"
d5c462fd
RR
73#include "bitmaps/vert.xpm"
74#include "bitmaps/alignt.xpm"
75#include "bitmaps/alignb.xpm"
76#include "bitmaps/horiz.xpm"
77#include "bitmaps/alignl.xpm"
78#include "bitmaps/alignr.xpm"
79#include "bitmaps/copysize.xpm"
80#include "bitmaps/tofront.xpm"
81#include "bitmaps/toback.xpm"
82#include "bitmaps/help.xpm"
83#include "bitmaps/wxwin.xpm"
457814b5
JS
84#endif
85
86/*
87 * Resource manager
88 */
89
ae8351fc
JS
90wxResourceManager::wxResourceManager():
91 m_imageList(16, 16, TRUE)
92{
93 sm_currentResourceManager = this;
94 m_editorFrame = NULL;
95 m_editorPanel = NULL;
96 m_popupMenu = NULL;
97 m_editorResourceTree = NULL;
98 m_editorControlList = NULL;
ae8351fc 99 m_nameCounter = 1;
5de76427 100 m_symbolIdCounter = 99;
ae8351fc
JS
101 m_modified = FALSE;
102 m_currentFilename = "";
03f68f12 103 m_symbolFilename = "";
ae8351fc 104 m_editorToolBar = NULL;
457814b5 105
457814b5 106 // Default window positions
ae8351fc
JS
107 m_resourceEditorWindowSize.width = 470;
108 m_resourceEditorWindowSize.height = 300;
457814b5 109
ae8351fc
JS
110 m_resourceEditorWindowSize.x = 0;
111 m_resourceEditorWindowSize.y = 0;
112
113 m_propertyWindowSize.width = 300;
114 m_propertyWindowSize.height = 300;
457814b5 115
d0fff5cb 116#ifdef __WXMSW__
ae8351fc 117 m_helpController = NULL;
b127f301 118#endif
ae8351fc
JS
119
120 m_bitmapImage = NULL;
121 m_rootDialogItem = 0;
457814b5
JS
122}
123
ae8351fc 124wxResourceManager::~wxResourceManager()
457814b5 125{
ae8351fc 126 sm_currentResourceManager = NULL;
457814b5
JS
127 SaveOptions();
128
d0fff5cb 129#ifdef __WXMSW__
ae8351fc
JS
130 if (m_helpController)
131 {
132 m_helpController->Quit();
133 delete m_helpController;
134 m_helpController = NULL;
135 }
b127f301
RR
136#endif
137
ae8351fc
JS
138 delete m_bitmapImage;
139 delete m_popupMenu;
457814b5
JS
140}
141
ae8351fc 142bool wxResourceManager::Initialize()
457814b5
JS
143{
144 // Set up the resource filename for each platform.
2049ba38 145#ifdef __WXMSW__
457814b5
JS
146 // dialoged.ini in the Windows directory
147 char buf[256];
148 GetWindowsDirectory(buf, 256);
149 strcat(buf, "\\dialoged.ini");
ae8351fc 150 m_optionsResourceFilename = buf;
b127f301 151#elif defined(__WXGTK__)
457814b5 152 char buf[500];
bbcdf8bc 153 wxGetHomeDir(buf);
ae8351fc
JS
154 strcat(buf, "/.dialogedrc");
155 m_optionsResourceFilename = buf;
457814b5
JS
156#else
157#error "Unsupported platform."
158#endif
159
160 LoadOptions();
161
d0fff5cb 162#ifdef __WXMSW__
ae8351fc
JS
163 m_helpController = new wxHelpController;
164 m_helpController->Initialize("dialoged");
b127f301 165#endif
457814b5 166
ae8351fc
JS
167 m_popupMenu = new wxMenu("", (wxFunction)ObjectMenuProc);
168 m_popupMenu->Append(OBJECT_MENU_EDIT, "Edit properties");
169 m_popupMenu->Append(OBJECT_MENU_DELETE, "Delete object");
170
171 if (!m_bitmapImage)
457814b5 172 {
2049ba38 173#ifdef __WXMSW__
ae8351fc 174 m_bitmapImage = new wxBitmap("WXWINBMP", wxBITMAP_TYPE_BMP_RESOURCE);
457814b5 175#endif
b127f301 176#ifdef __WXGTK__
d5c462fd 177 m_bitmapImage = new wxBitmap( wxwin_xpm );
457814b5
JS
178#endif
179 }
ae8351fc
JS
180
181 // Initialize the image list icons
2049ba38 182#ifdef __WXMSW__
ae8351fc
JS
183 wxIcon icon1("DIALOG_ICON", wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);
184 wxIcon icon2("FOLDER1_ICON", wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);
185 wxIcon icon3("FOLDER2_ICON", wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);
186 wxIcon icon4("BUTTONSM_ICON", wxBITMAP_TYPE_ICO_RESOURCE, 16, 16);
187 m_imageList.Add(icon1);
188 m_imageList.Add(icon2);
189 m_imageList.Add(icon3);
190 m_imageList.Add(icon4);
191#endif
192
5de76427
JS
193 m_symbolTable.AddStandardSymbols();
194
457814b5
JS
195 return TRUE;
196}
197
ae8351fc 198bool wxResourceManager::LoadOptions()
457814b5 199{
ae8351fc
JS
200 wxGetResource("DialogEd", "editorWindowX", &m_resourceEditorWindowSize.x, m_optionsResourceFilename.GetData());
201 wxGetResource("DialogEd", "editorWindowY", &m_resourceEditorWindowSize.y, m_optionsResourceFilename.GetData());
202 wxGetResource("DialogEd", "editorWindowWidth", &m_resourceEditorWindowSize.width, m_optionsResourceFilename.GetData());
203 wxGetResource("DialogEd", "editorWindowHeight", &m_resourceEditorWindowSize.height, m_optionsResourceFilename.GetData());
204 wxGetResource("DialogEd", "propertyWindowX", &m_propertyWindowSize.x, m_optionsResourceFilename.GetData());
205 wxGetResource("DialogEd", "propertyWindowY", &m_propertyWindowSize.y, m_optionsResourceFilename.GetData());
206 wxGetResource("DialogEd", "propertyWindowWidth", &m_propertyWindowSize.width, m_optionsResourceFilename.GetData());
207 wxGetResource("DialogEd", "propertyWindowHeight", &m_propertyWindowSize.height, m_optionsResourceFilename.GetData());
457814b5
JS
208 return TRUE;
209}
210
ae8351fc 211bool wxResourceManager::SaveOptions()
457814b5 212{
ae8351fc
JS
213 wxWriteResource("DialogEd", "editorWindowX", m_resourceEditorWindowSize.x, m_optionsResourceFilename.GetData());
214 wxWriteResource("DialogEd", "editorWindowY", m_resourceEditorWindowSize.y, m_optionsResourceFilename.GetData());
215 wxWriteResource("DialogEd", "editorWindowWidth", m_resourceEditorWindowSize.width, m_optionsResourceFilename.GetData());
216 wxWriteResource("DialogEd", "editorWindowHeight", m_resourceEditorWindowSize.height, m_optionsResourceFilename.GetData());
217
218 wxWriteResource("DialogEd", "propertyWindowX", m_propertyWindowSize.x, m_optionsResourceFilename.GetData());
219 wxWriteResource("DialogEd", "propertyWindowY", m_propertyWindowSize.y, m_optionsResourceFilename.GetData());
220 wxWriteResource("DialogEd", "propertyWindowWidth", m_propertyWindowSize.width, m_optionsResourceFilename.GetData());
221 wxWriteResource("DialogEd", "propertyWindowHeight", m_propertyWindowSize.height, m_optionsResourceFilename.GetData());
457814b5 222
457814b5
JS
223 return TRUE;
224}
225
226// Show or hide the resource editor frame, which displays a list
227// of resources with ability to edit them.
b127f301 228bool wxResourceManager::ShowResourceEditor(bool show, wxWindow *WXUNUSED(parent), const char *title)
457814b5
JS
229{
230 if (show)
231 {
ae8351fc 232 if (m_editorFrame)
457814b5 233 {
ae8351fc
JS
234 m_editorFrame->Iconize(FALSE);
235 m_editorFrame->Show(TRUE);
457814b5
JS
236 return TRUE;
237 }
ae8351fc 238 m_editorFrame = OnCreateEditorFrame(title);
457814b5 239 SetFrameTitle("");
ae8351fc
JS
240 wxMenuBar *menuBar = OnCreateEditorMenuBar(m_editorFrame);
241 m_editorFrame->SetMenuBar(menuBar);
242
243 m_editorToolBar = (EditorToolBar *)OnCreateToolBar(m_editorFrame);
ae8351fc
JS
244 m_editorControlList = new wxResourceEditorControlList(m_editorFrame, IDC_LISTCTRL, wxPoint(0, 0), wxSize(-1, -1));
245 m_editorResourceTree = new wxResourceEditorProjectTree(m_editorFrame, IDC_TREECTRL, wxPoint(0, 0), wxSize(-1, -1),
246 wxTR_HAS_BUTTONS);
247 m_editorPanel = OnCreateEditorPanel(m_editorFrame);
248
249 m_editorResourceTree->SetImageList(& m_imageList);
457814b5
JS
250
251 // Constraints for toolbar
252 wxLayoutConstraints *c = new wxLayoutConstraints;
ae8351fc
JS
253 c->left.SameAs (m_editorFrame, wxLeft, 0);
254 c->top.SameAs (m_editorFrame, wxTop, 0);
255 c->right.SameAs (m_editorFrame, wxRight, 0);
256 c->bottom.Unconstrained();
457814b5
JS
257 c->width.Unconstrained();
258 c->height.Absolute(28);
ae8351fc 259 m_editorToolBar->SetConstraints(c);
03f68f12 260
ae8351fc
JS
261 // Constraints for listbox
262 c = new wxLayoutConstraints;
263 c->left.SameAs (m_editorFrame, wxLeft, 0);
264 c->top.SameAs (m_editorToolBar, wxBottom, 0);
265 c->right.Absolute (150);
266 c->bottom.SameAs (m_editorControlList, wxTop, 0);
267 c->width.Unconstrained();
268 c->height.Unconstrained();
269 m_editorResourceTree->SetConstraints(c);
457814b5
JS
270
271 // Constraints for panel
272 c = new wxLayoutConstraints;
ae8351fc
JS
273 c->left.SameAs (m_editorResourceTree, wxRight, 0);
274 c->top.SameAs (m_editorToolBar, wxBottom, 0);
275 c->right.SameAs (m_editorFrame, wxRight, 0);
276 c->bottom.SameAs (m_editorControlList, wxTop, 0);
457814b5
JS
277 c->width.Unconstrained();
278 c->height.Unconstrained();
ae8351fc
JS
279 m_editorPanel->SetConstraints(c);
280
281 // Constraints for control list (bottom window)
282 c = new wxLayoutConstraints;
283 c->left.SameAs (m_editorFrame, wxLeft, 0);
284 c->right.SameAs (m_editorFrame, wxRight, 0);
285 c->bottom.SameAs (m_editorFrame, wxBottom, 0);
286 c->width.Unconstrained();
b127f301
RR
287#ifdef __WXGTK__
288 c->height.Absolute(70);
289#else
ae8351fc 290 c->height.Absolute(60);
b127f301
RR
291#endif
292
ae8351fc 293 m_editorControlList->SetConstraints(c);
457814b5 294
ae8351fc 295 m_editorFrame->SetAutoLayout(TRUE);
457814b5
JS
296
297 UpdateResourceList();
ae8351fc
JS
298
299 m_editorFrame->Show(TRUE);
457814b5
JS
300 return TRUE;
301 }
302 else
303 {
ae8351fc
JS
304 wxFrame *fr = m_editorFrame;
305 if (m_editorFrame->OnClose())
457814b5
JS
306 {
307 fr->Show(FALSE);
308 delete fr;
ae8351fc
JS
309 m_editorFrame = NULL;
310 m_editorPanel = NULL;
457814b5
JS
311 }
312 }
313 return TRUE;
314}
315
316void wxResourceManager::SetFrameTitle(const wxString& filename)
317{
ae8351fc 318 if (m_editorFrame)
457814b5
JS
319 {
320 if (filename == wxString(""))
ae8351fc 321 m_editorFrame->SetTitle("wxWindows Dialog Editor - untitled");
457814b5
JS
322 else
323 {
324 wxString str("wxWindows Dialog Editor - ");
325 wxString str2(wxFileNameFromPath(WXSTRINGCAST filename));
326 str += str2;
ae8351fc 327 m_editorFrame->SetTitle(str);
457814b5
JS
328 }
329 }
330}
331
ae8351fc 332bool wxResourceManager::Save()
457814b5 333{
ae8351fc 334 if (m_currentFilename == wxString(""))
457814b5
JS
335 return SaveAs();
336 else
ae8351fc 337 return Save(m_currentFilename);
457814b5
JS
338}
339
340bool wxResourceManager::Save(const wxString& filename)
341{
342 // Ensure all visible windows are saved to their resources
ae8351fc
JS
343 m_currentFilename = filename;
344 SetFrameTitle(m_currentFilename);
457814b5 345 InstantiateAllResourcesFromWindows();
ae8351fc 346 if (m_resourceTable.Save(filename))
457814b5 347 {
bbcdf8bc 348 m_symbolTable.WriteIncludeFile(m_symbolFilename);
457814b5
JS
349 Modify(FALSE);
350 return TRUE;
351 }
352 else
353 return FALSE;
354}
355
ae8351fc 356bool wxResourceManager::SaveAs()
457814b5 357{
ae8351fc 358 wxString s(wxFileSelector("Save resource file", wxPathOnly(WXSTRINGCAST m_currentFilename), wxFileNameFromPath(WXSTRINGCAST m_currentFilename),
457814b5
JS
359 "wxr", "*.wxr", wxSAVE | wxOVERWRITE_PROMPT));
360
361 if (s.IsNull() || s == "")
362 return FALSE;
363
ae8351fc 364 m_currentFilename = s;
bbcdf8bc
JS
365 wxStripExtension(m_currentFilename);
366 m_currentFilename += ".wxr";
367
368 // Construct include filename from this file
369 m_symbolFilename = m_currentFilename;
370
371 wxStripExtension(m_symbolFilename);
372 m_symbolFilename += ".h";
373
ae8351fc 374 Save(m_currentFilename);
457814b5
JS
375 return TRUE;
376}
377
ae8351fc 378bool wxResourceManager::SaveIfModified()
457814b5
JS
379{
380 if (Modified())
381 return Save();
382 else return TRUE;
383}
384
385bool wxResourceManager::Load(const wxString& filename)
386{
387 return New(TRUE, filename);
388}
389
390bool wxResourceManager::New(bool loadFromFile, const wxString& filename)
391{
392 if (!Clear(TRUE, FALSE))
393 return FALSE;
394
5de76427
JS
395 m_symbolTable.AddStandardSymbols();
396
457814b5
JS
397 if (loadFromFile)
398 {
399 wxString str = filename;
400 if (str == wxString(""))
401 {
402 wxString f(wxFileSelector("Open resource file", NULL, NULL, "wxr", "*.wxr", 0, NULL));
403 if (!f.IsNull() && f != "")
404 str = f;
405 else
406 return FALSE;
407 }
408
ae8351fc 409 if (!m_resourceTable.ParseResourceFile(WXSTRINGCAST str))
457814b5
JS
410 {
411 wxMessageBox("Could not read file.", "Resource file load error", wxOK | wxICON_EXCLAMATION);
412 return FALSE;
413 }
ae8351fc
JS
414 m_currentFilename = str;
415
416 SetFrameTitle(m_currentFilename);
417
457814b5 418 UpdateResourceList();
03f68f12
JS
419
420 // Construct include filename from this file
421 m_symbolFilename = m_currentFilename;
422
5de76427 423 wxStripExtension(m_symbolFilename);
03f68f12
JS
424 m_symbolFilename += ".h";
425
426 if (!m_symbolTable.ReadIncludeFile(m_symbolFilename))
427 {
428 wxString str("Could not find include file ");
429 str += m_symbolFilename;
bbcdf8bc
JS
430 str += ".\nDialog Editor maintains a header file containing id symbols to be used in the application.\n";
431 str += "The next time this .wxr file is saved, a header file will be saved also.";
b127f301 432 wxMessageBox(str, "Dialog Editor Warning", wxOK );
5de76427
JS
433
434 m_symbolIdCounter = 99;
435 }
436 else
437 {
438 // Set the id counter to the last known id
439 m_symbolIdCounter = m_symbolTable.FindHighestId();
03f68f12 440 }
bbcdf8bc
JS
441
442 // Now check in case some (or all) resources don't have resource ids, or they
443 // don't match the .h file, or something of that nature.
444 bool altered = RepairResourceIds();
445 if (altered)
446 {
b127f301
RR
447 wxMessageBox("Some resources have had new identifiers associated with them, since they were missing.",
448 "Dialog Editor Warning", wxOK );
bbcdf8bc
JS
449 Modify(TRUE);
450 }
451 else
452 Modify(FALSE);
453
454 return TRUE;
457814b5
JS
455 }
456 else
457 {
458 SetFrameTitle("");
ae8351fc 459 m_currentFilename = "";
457814b5
JS
460 }
461 Modify(FALSE);
462
463 return TRUE;
464}
465
b127f301 466bool wxResourceManager::Clear(bool WXUNUSED(deleteWindows), bool force)
457814b5
JS
467{
468 if (!force && Modified())
469 {
470 int ans = wxMessageBox("Save modified resource file?", "Dialog Editor", wxYES_NO | wxCANCEL);
471 if (ans == wxCANCEL)
472 return FALSE;
473 if (ans == wxYES)
474 if (!SaveIfModified())
475 return FALSE;
476 if (ans == wxNO)
477 Modify(FALSE);
478 }
479
ae8351fc
JS
480 ClearCurrentDialog();
481 DisassociateWindows();
457814b5 482
03f68f12 483 m_symbolTable.Clear();
ae8351fc 484 m_resourceTable.ClearTable();
457814b5
JS
485 UpdateResourceList();
486
487 return TRUE;
488}
489
ae8351fc 490bool wxResourceManager::DisassociateWindows()
457814b5 491{
ae8351fc 492 m_resourceTable.BeginFind();
457814b5 493 wxNode *node;
ae8351fc 494 while (node = m_resourceTable.Next())
457814b5
JS
495 {
496 wxItemResource *res = (wxItemResource *)node->Data();
ae8351fc 497 DisassociateResource(res);
457814b5
JS
498 }
499
500 return TRUE;
501}
502
503void wxResourceManager::AssociateResource(wxItemResource *resource, wxWindow *win)
504{
ae8351fc
JS
505 if (!m_resourceAssociations.Get((long)resource))
506 m_resourceAssociations.Put((long)resource, win);
507
457814b5
JS
508 wxNode *node = resource->GetChildren().First();
509 while (node)
510 {
511 wxItemResource *child = (wxItemResource *)node->Data();
ae8351fc 512 wxWindow *childWindow = (wxWindow *)m_resourceAssociations.Get((long)child);
457814b5
JS
513 if (!childWindow)
514 childWindow = win->FindWindow(child->GetName());
515 if (childWindow)
516 AssociateResource(child, childWindow);
517 else
518 {
519 char buf[200];
520 sprintf(buf, "AssociateResource: cannot find child window %s", child->GetName() ? child->GetName() : "(unnamed)");
521 wxMessageBox(buf, "Dialog Editor problem", wxOK);
522 }
523
524 node = node->Next();
525 }
526}
527
ae8351fc 528bool wxResourceManager::DisassociateResource(wxItemResource *resource)
457814b5
JS
529{
530 wxWindow *win = FindWindowForResource(resource);
531 if (!win)
532 return FALSE;
533
ae8351fc 534 // Disassociate children of window
457814b5
JS
535 if (win->GetChildren())
536 {
537 wxNode *node = win->GetChildren()->First();
538 while (node)
539 {
540 wxWindow *child = (wxWindow *)node->Data();
541 if (child->IsKindOf(CLASSINFO(wxControl)))
ae8351fc 542 DisassociateResource(child);
457814b5
JS
543 node = node->Next();
544 }
545 }
546
457814b5 547 RemoveSelection(win);
ae8351fc 548 m_resourceAssociations.Delete((long)resource);
457814b5
JS
549 return TRUE;
550}
551
ae8351fc 552bool wxResourceManager::DisassociateResource(wxWindow *win)
457814b5
JS
553{
554 wxItemResource *res = FindResourceForWindow(win);
555 if (res)
ae8351fc
JS
556 return DisassociateResource(res);
557 else
558 return FALSE;
559}
560
561// Saves the window info into the resource, and deletes the
562// handler. Doesn't actually disassociate the window from
563// the resources. Replaces OnClose.
564bool wxResourceManager::SaveInfoAndDeleteHandler(wxWindow* win)
565{
566 wxItemResource *res = FindResourceForWindow(win);
567
568 if (win->IsKindOf(CLASSINFO(wxPanel)))
569 {
570 wxResourceEditorDialogHandler* handler = (wxResourceEditorDialogHandler*) win->GetEventHandler();
571 win->PopEventHandler();
572
573 // Now reset all child event handlers
574 wxNode *node = win->GetChildren()->First();
575 while ( node )
576 {
577 wxWindow *child = (wxWindow *)node->Data();
578 wxEvtHandler *childHandler = child->GetEventHandler();
579 if ( child->IsKindOf(CLASSINFO(wxControl)) && childHandler != child )
580 {
581 child->PopEventHandler(TRUE);
582 }
583 node = node->Next();
584 }
585 delete handler;
586 }
587 else
588 {
589 win->PopEventHandler(TRUE);
590 }
591
592 // Save the information
593 InstantiateResourceFromWindow(res, win, TRUE);
594
595// DisassociateResource(win);
596
597 return TRUE;
598}
599
600// Destroys the window. If this is the 'current' panel, NULLs the
601// variable.
602bool wxResourceManager::DeleteWindow(wxWindow* win)
603{
03f68f12 604 bool clearDisplay = FALSE;
ae8351fc 605 if (m_editorPanel->m_childWindow == win)
03f68f12 606 {
ae8351fc 607 m_editorPanel->m_childWindow = NULL;
03f68f12
JS
608 clearDisplay = TRUE;
609 }
ae8351fc
JS
610
611 win->Destroy();
03f68f12
JS
612
613 if (clearDisplay)
614 m_editorPanel->Clear();
615
ae8351fc 616 return TRUE;
457814b5
JS
617}
618
619wxItemResource *wxResourceManager::FindResourceForWindow(wxWindow *win)
620{
ae8351fc 621 m_resourceAssociations.BeginFind();
457814b5 622 wxNode *node;
ae8351fc 623 while (node = m_resourceAssociations.Next())
457814b5
JS
624 {
625 wxWindow *w = (wxWindow *)node->Data();
626 if (w == win)
627 {
628 return (wxItemResource *)node->key.integer;
629 }
630 }
631 return NULL;
632}
633
634wxWindow *wxResourceManager::FindWindowForResource(wxItemResource *resource)
635{
ae8351fc 636 return (wxWindow *)m_resourceAssociations.Get((long)resource);
457814b5
JS
637}
638
639
640void wxResourceManager::MakeUniqueName(char *prefix, char *buf)
641{
642 while (TRUE)
643 {
ae8351fc
JS
644 sprintf(buf, "%s%d", prefix, m_nameCounter);
645 m_nameCounter ++;
646
647 if (!m_resourceTable.FindResource(buf))
457814b5
JS
648 return;
649 }
650}
651
652wxFrame *wxResourceManager::OnCreateEditorFrame(const char *title)
653{
654 int frameWidth = 420;
655 int frameHeight = 300;
656
ae8351fc
JS
657 wxResourceEditorFrame *frame = new wxResourceEditorFrame(this, NULL, title,
658 wxPoint(m_resourceEditorWindowSize.x, m_resourceEditorWindowSize.y),
659 wxSize(m_resourceEditorWindowSize.width, m_resourceEditorWindowSize.height),
660 wxDEFAULT_FRAME_STYLE);
457814b5 661
ae8351fc 662 frame->CreateStatusBar(1);
457814b5 663
457814b5 664 frame->SetAutoLayout(TRUE);
2049ba38 665#ifdef __WXMSW__
457814b5
JS
666 wxIcon *icon = new wxIcon("DIALOGEDICON");
667 frame->SetIcon(icon);
668#endif
669 return frame;
670}
671
b127f301 672wxMenuBar *wxResourceManager::OnCreateEditorMenuBar(wxFrame *WXUNUSED(parent))
457814b5
JS
673{
674 wxMenuBar *menuBar = new wxMenuBar;
675
676 wxMenu *fileMenu = new wxMenu;
677 fileMenu->Append(RESED_NEW_DIALOG, "New &dialog", "Create a new dialog");
457814b5
JS
678 fileMenu->AppendSeparator();
679 fileMenu->Append(wxID_NEW, "&New project", "Clear the current project");
680 fileMenu->Append(wxID_OPEN, "&Open...", "Load a resource file");
681 fileMenu->Append(wxID_SAVE, "&Save", "Save a resource file");
682 fileMenu->Append(wxID_SAVEAS, "Save &As...", "Save a resource file as...");
683 fileMenu->Append(RESED_CLEAR, "&Clear", "Clear current resources");
684 fileMenu->AppendSeparator();
685 fileMenu->Append(wxID_EXIT, "E&xit", "Exit resource editor");
686
687 wxMenu *editMenu = new wxMenu;
ae8351fc 688 editMenu->Append(RESED_TEST, "&Test Dialog", "Test dialog");
457814b5
JS
689 editMenu->Append(RESED_RECREATE, "&Recreate", "Recreate the selected resource(s)");
690 editMenu->Append(RESED_DELETE, "&Delete", "Delete the selected resource(s)");
457814b5
JS
691
692 wxMenu *helpMenu = new wxMenu;
693 helpMenu->Append(RESED_CONTENTS, "&Help topics", "Invokes the on-line help");
694 helpMenu->AppendSeparator();
695 helpMenu->Append(wxID_ABOUT, "&About", "About wxWindows Dialog Editor");
696
697 menuBar->Append(fileMenu, "&File");
698 menuBar->Append(editMenu, "&Edit");
699 menuBar->Append(helpMenu, "&Help");
700
701 return menuBar;
702}
703
ae8351fc 704wxResourceEditorScrolledWindow *wxResourceManager::OnCreateEditorPanel(wxFrame *parent)
457814b5 705{
ae8351fc
JS
706 wxResourceEditorScrolledWindow *panel = new wxResourceEditorScrolledWindow(parent, wxDefaultPosition, wxDefaultSize,
707// wxSUNKEN_BORDER|wxCLIP_CHILDREN);
708 wxSUNKEN_BORDER);
457814b5 709
ae8351fc 710 panel->SetScrollbars(10, 10, 100, 100);
457814b5
JS
711
712 return panel;
713}
714
163f0dbe 715wxToolBar *wxResourceManager::OnCreateToolBar(wxFrame *parent)
457814b5
JS
716{
717 // Load palette bitmaps
2049ba38 718#ifdef __WXMSW__
ae8351fc
JS
719 wxBitmap ToolbarLoadBitmap("LOADTOOL");
720 wxBitmap ToolbarSaveBitmap("SAVETOOL");
721 wxBitmap ToolbarNewBitmap("NEWTOOL");
722 wxBitmap ToolbarVertBitmap("VERTTOOL");
723 wxBitmap ToolbarAlignTBitmap("ALIGNTTOOL");
724 wxBitmap ToolbarAlignBBitmap("ALIGNBTOOL");
725 wxBitmap ToolbarHorizBitmap("HORIZTOOL");
726 wxBitmap ToolbarAlignLBitmap("ALIGNLTOOL");
727 wxBitmap ToolbarAlignRBitmap("ALIGNRTOOL");
728 wxBitmap ToolbarCopySizeBitmap("COPYSIZETOOL");
729 wxBitmap ToolbarToBackBitmap("TOBACKTOOL");
730 wxBitmap ToolbarToFrontBitmap("TOFRONTTOOL");
731 wxBitmap ToolbarHelpBitmap("HELPTOOL");
457814b5 732#endif
b127f301
RR
733#ifdef __WXGTK__
734 wxBitmap ToolbarLoadBitmap( load_xpm );
735 wxBitmap ToolbarSaveBitmap( save_xpm);
736 wxBitmap ToolbarNewBitmap( new_xpm );
d5c462fd
RR
737 wxBitmap ToolbarVertBitmap( vert_xpm );
738 wxBitmap ToolbarAlignTBitmap( alignt_xpm );
739 wxBitmap ToolbarAlignBBitmap( alignb_xpm );
740 wxBitmap ToolbarHorizBitmap( horiz_xpm );
741 wxBitmap ToolbarAlignLBitmap( alignl_xpm );
742 wxBitmap ToolbarAlignRBitmap( alignr_xpm );
743 wxBitmap ToolbarCopySizeBitmap( copysize_xpm );
744 wxBitmap ToolbarToBackBitmap( toback_xpm );
745 wxBitmap ToolbarToFrontBitmap( tofront_xpm );
746 wxBitmap ToolbarHelpBitmap( help_xpm );
457814b5
JS
747#endif
748
749 // Create the toolbar
f449ef69 750 EditorToolBar *toolbar = new EditorToolBar(parent, wxPoint(0, 0), wxSize(-1, -1), wxNO_BORDER|wxTB_HORIZONTAL);
457814b5 751 toolbar->SetMargins(2, 2);
457814b5 752
2049ba38 753#ifdef __WXMSW__
457814b5
JS
754 int width = 24;
755 int dx = 2;
756 int gap = 6;
757#else
b127f301 758 int width = 24; // ToolbarLoadBitmap->GetWidth(); ???
457814b5
JS
759 int dx = 2;
760 int gap = 6;
761#endif
762 int currentX = gap;
763 toolbar->AddSeparator();
764 toolbar->AddTool(TOOLBAR_NEW, ToolbarNewBitmap, (wxBitmap *)NULL,
765 FALSE, (float)currentX, -1, NULL, "New dialog");
766 currentX += width + dx;
767 toolbar->AddTool(TOOLBAR_LOAD_FILE, ToolbarLoadBitmap, (wxBitmap *)NULL,
768 FALSE, (float)currentX, -1, NULL, "Load");
769 currentX += width + dx;
770 toolbar->AddTool(TOOLBAR_SAVE_FILE, ToolbarSaveBitmap, (wxBitmap *)NULL,
771 FALSE, (float)currentX, -1, NULL, "Save");
772 currentX += width + dx + gap;
773 toolbar->AddSeparator();
774 toolbar->AddTool(TOOLBAR_FORMAT_HORIZ, ToolbarVertBitmap, (wxBitmap *)NULL,
775 FALSE, (float)currentX, -1, NULL, "Horizontal align");
776 currentX += width + dx;
777 toolbar->AddTool(TOOLBAR_FORMAT_VERT_TOP_ALIGN, ToolbarAlignTBitmap, (wxBitmap *)NULL,
778 FALSE, (float)currentX, -1, NULL, "Top align");
779 currentX += width + dx;
780 toolbar->AddTool(TOOLBAR_FORMAT_VERT_BOT_ALIGN, ToolbarAlignBBitmap, (wxBitmap *)NULL,
781 FALSE, (float)currentX, -1, NULL, "Bottom align");
782 currentX += width + dx;
783 toolbar->AddTool(TOOLBAR_FORMAT_VERT, ToolbarHorizBitmap, (wxBitmap *)NULL,
784 FALSE, (float)currentX, -1, NULL, "Vertical align");
785 currentX += width + dx;
786 toolbar->AddTool(TOOLBAR_FORMAT_HORIZ_LEFT_ALIGN, ToolbarAlignLBitmap, (wxBitmap *)NULL,
787 FALSE, (float)currentX, -1, NULL, "Left align");
788 currentX += width + dx;
789 toolbar->AddTool(TOOLBAR_FORMAT_HORIZ_RIGHT_ALIGN, ToolbarAlignRBitmap, (wxBitmap *)NULL,
790 FALSE, (float)currentX, -1, NULL, "Right align");
791 currentX += width + dx;
792 toolbar->AddTool(TOOLBAR_COPY_SIZE, ToolbarCopySizeBitmap, (wxBitmap *)NULL,
793 FALSE, (float)currentX, -1, NULL, "Copy size");
794 currentX += width + dx + gap;
795 toolbar->AddSeparator();
796 toolbar->AddTool(TOOLBAR_TO_FRONT, ToolbarToFrontBitmap, (wxBitmap *)NULL,
797 FALSE, (float)currentX, -1, NULL, "To front");
798 currentX += width + dx;
799 toolbar->AddTool(TOOLBAR_TO_BACK, ToolbarToBackBitmap, (wxBitmap *)NULL,
800 FALSE, (float)currentX, -1, NULL, "To back");
801 currentX += width + dx + gap;
457814b5 802
457814b5
JS
803 toolbar->AddSeparator();
804 toolbar->AddTool(TOOLBAR_HELP, ToolbarHelpBitmap, (wxBitmap *)NULL,
805 FALSE, (float)currentX, -1, NULL, "Help");
806 currentX += width + dx;
807
f449ef69 808 toolbar->Realize();
457814b5
JS
809
810 return toolbar;
457814b5
JS
811}
812
ae8351fc 813void wxResourceManager::UpdateResourceList()
457814b5 814{
ae8351fc
JS
815 if (!m_editorResourceTree)
816 return;
817
818 m_editorResourceTree->SetInvalid(TRUE);
819 m_editorResourceTree->DeleteAllItems();
820
821 long id = m_editorResourceTree->InsertItem(0, "Dialogs"
2049ba38 822#ifdef __WXMSW__
ae8351fc
JS
823 , 1, 2
824#endif
825 );
826
827 m_resourceTable.BeginFind();
457814b5 828 wxNode *node;
ae8351fc 829 while (node = m_resourceTable.Next())
457814b5
JS
830 {
831 wxItemResource *res = (wxItemResource *)node->Data();
832 wxString resType(res->GetType());
457814b5
JS
833 if (resType == "wxDialog" || resType == "wxDialogBox" || resType == "wxPanel" || resType == "wxBitmap")
834 {
ae8351fc 835 AddItemsRecursively(id, res);
457814b5
JS
836 }
837 }
ae8351fc
JS
838 m_editorResourceTree->ExpandItem(id, wxTREE_EXPAND_EXPAND);
839 m_editorResourceTree->SetInvalid(FALSE);
457814b5
JS
840}
841
ae8351fc 842void wxResourceManager::AddItemsRecursively(long parent, wxItemResource *resource)
457814b5 843{
457814b5 844 wxString theString("");
ae8351fc
JS
845 theString = resource->GetName();
846
847 int imageId = 0;
848 wxString resType(resource->GetType());
849 if (resType == "wxDialog" || resType == "wxDialogBox" || resType == "wxPanel")
850 imageId = 0;
851 else
852 imageId = 3;
457814b5 853
ae8351fc 854 long id = m_editorResourceTree->InsertItem(parent, theString
2049ba38 855#ifdef __WXMSW__
ae8351fc
JS
856 , imageId
857#endif
858 );
859
860 m_editorResourceTree->SetItemData(id, (long) resource);
457814b5
JS
861
862 if (strcmp(resource->GetType(), "wxBitmap") != 0)
863 {
864 wxNode *node = resource->GetChildren().First();
865 while (node)
866 {
867 wxItemResource *res = (wxItemResource *)node->Data();
ae8351fc 868 AddItemsRecursively(id, res);
457814b5
JS
869 node = node->Next();
870 }
871 }
ae8351fc 872 m_editorResourceTree->ExpandItem(id, wxTREE_EXPAND_EXPAND);
457814b5
JS
873}
874
ae8351fc 875bool wxResourceManager::EditSelectedResource()
457814b5 876{
ae8351fc 877 int sel = m_editorResourceTree->GetSelection();
03f68f12 878 if (sel != 0)
457814b5 879 {
ae8351fc 880 wxItemResource *res = (wxItemResource *)m_editorResourceTree->GetItemData(sel);
457814b5
JS
881 return Edit(res);
882 }
883 return FALSE;
884}
885
886bool wxResourceManager::Edit(wxItemResource *res)
887{
ae8351fc
JS
888 ClearCurrentDialog();
889
457814b5 890 wxString resType(res->GetType());
ae8351fc 891 wxPanel *panel = (wxPanel *)FindWindowForResource(res);
457814b5 892
ae8351fc
JS
893 if (panel)
894 {
895 wxMessageBox("Should not find panel in wxResourceManager::Edit");
896 return FALSE;
897 }
898 else
899 {
900 long style = res->GetStyle();
901 res->SetStyle(style|wxRAISED_BORDER);
457814b5
JS
902 panel = new wxPanel;
903 wxResourceEditorDialogHandler *handler = new wxResourceEditorDialogHandler(panel, res, panel->GetEventHandler(),
904 this);
457814b5 905
ae8351fc 906 panel->LoadFromResource(m_editorPanel, res->GetName(), &m_resourceTable);
457814b5 907
ae8351fc 908 panel->PushEventHandler(handler);
457814b5 909
ae8351fc
JS
910 res->SetStyle(style);
911 handler->AddChildHandlers(); // Add event handlers for all controls
912 AssociateResource(res, panel);
457814b5 913
ae8351fc
JS
914 m_editorPanel->m_childWindow = panel;
915 panel->Move(m_editorPanel->GetMarginX(), m_editorPanel->GetMarginY());
916 panel->Show(TRUE);
917 panel->Refresh();
457814b5 918
ae8351fc
JS
919 wxClientDC dc(m_editorPanel);
920 m_editorPanel->DrawTitle(dc);
921 }
922 return FALSE;
457814b5
JS
923}
924
ae8351fc 925bool wxResourceManager::CreateNewPanel()
457814b5 926{
ae8351fc
JS
927 ClearCurrentDialog();
928
457814b5 929 char buf[256];
bbcdf8bc 930 MakeUniqueName("dialog", buf);
457814b5
JS
931
932 wxItemResource *resource = new wxItemResource;
bbcdf8bc 933 resource->SetType("wxDialog");
457814b5
JS
934 resource->SetName(buf);
935 resource->SetTitle(buf);
5de76427
JS
936
937 wxString newIdName;
938 int id = GenerateWindowId("ID_DIALOG", newIdName);
939 resource->SetId(id);
940
941 // This is now guaranteed to be unique, so just add to symbol table
942 m_symbolTable.AddSymbol(newIdName, id);
943
ae8351fc 944 m_resourceTable.AddResource(resource);
457814b5 945
ae8351fc
JS
946 wxPanel *panel = new wxPanel(m_editorPanel, -1,
947 wxPoint(m_editorPanel->GetMarginX(), m_editorPanel->GetMarginY()),
bbcdf8bc 948 wxSize(400, 300), wxRAISED_BORDER|wxDEFAULT_DIALOG_STYLE, buf);
ae8351fc 949 m_editorPanel->m_childWindow = panel;
457814b5 950
bbcdf8bc 951 resource->SetStyle(panel->GetWindowStyleFlag());
ae8351fc 952 resource->SetSize(10, 10, 400, 300);
457814b5
JS
953
954 // For editing in situ we will need to use the hash table to ensure
955 // we don't dereference invalid pointers.
956// resourceWindowTable.Put((long)resource, panel);
957
958 wxResourceEditorDialogHandler *handler = new wxResourceEditorDialogHandler(panel, resource, panel->GetEventHandler(),
959 this);
960 panel->PushEventHandler(handler);
961
457814b5 962 AssociateResource(resource, panel);
457814b5
JS
963 UpdateResourceList();
964
965 Modify(TRUE);
ae8351fc
JS
966 m_editorPanel->m_childWindow->Refresh();
967
968// panel->Refresh();
969
970 wxClientDC dc(m_editorPanel);
971 m_editorPanel->DrawTitle(dc);
972
457814b5
JS
973 return TRUE;
974}
975
976bool wxResourceManager::CreatePanelItem(wxItemResource *panelResource, wxPanel *panel, char *iType, int x, int y, bool isBitmap)
977{
978 char buf[256];
979 if (!panel->IsKindOf(CLASSINFO(wxPanel)) && !panel->IsKindOf(CLASSINFO(wxDialog)))
980 return FALSE;
981
982 Modify(TRUE);
983
984 wxItemResource *res = new wxItemResource;
985 wxControl *newItem = NULL;
986 res->SetSize(x, y, -1, -1);
987 res->SetType(iType);
5de76427
JS
988
989 wxString prefix;
457814b5
JS
990
991 wxString itemType(iType);
992
993 if (itemType == "wxButton")
994 {
5de76427 995 prefix = "ID_BUTTON";
457814b5
JS
996 MakeUniqueName("button", buf);
997 res->SetName(buf);
998 if (isBitmap)
ae8351fc 999 newItem = new wxBitmapButton(panel, -1, m_bitmapImage, wxPoint(x, y), wxSize(-1, -1), 0, wxDefaultValidator, buf);
457814b5
JS
1000 else
1001 newItem = new wxButton(panel, -1, "Button", wxPoint(x, y), wxSize(-1, -1), 0, wxDefaultValidator, buf);
1002 }
1003 if (itemType == "wxBitmapButton")
1004 {
5de76427 1005 prefix = "ID_BITMAPBUTTON";
457814b5
JS
1006 MakeUniqueName("button", buf);
1007 res->SetName(buf);
ae8351fc 1008 newItem = new wxBitmapButton(panel, -1, m_bitmapImage, wxPoint(x, y), wxSize(-1, -1), 0, wxDefaultValidator, buf);
457814b5
JS
1009 }
1010 else if (itemType == "wxMessage" || itemType == "wxStaticText")
1011 {
5de76427 1012 prefix = "ID_STATIC";
9c331ded 1013 MakeUniqueName("statictext", buf);
457814b5
JS
1014 res->SetName(buf);
1015 if (isBitmap)
ae8351fc 1016 newItem = new wxStaticBitmap(panel, -1, m_bitmapImage, wxPoint(x, y), wxSize(0, 0), 0, buf);
457814b5 1017 else
9c331ded 1018 newItem = new wxStaticText(panel, -1, "Static", wxPoint(x, y), wxSize(-1, -1), 0, buf);
457814b5
JS
1019 }
1020 else if (itemType == "wxStaticBitmap")
1021 {
5de76427 1022 prefix = "ID_STATICBITMAP";
9c331ded 1023 MakeUniqueName("static", buf);
457814b5 1024 res->SetName(buf);
ae8351fc 1025 newItem = new wxStaticBitmap(panel, -1, m_bitmapImage, wxPoint(x, y), wxSize(-1, -1), 0, buf);
457814b5
JS
1026 }
1027 else if (itemType == "wxCheckBox")
1028 {
5de76427 1029 prefix = "ID_CHECKBOX";
457814b5
JS
1030 MakeUniqueName("checkbox", buf);
1031 res->SetName(buf);
1032 newItem = new wxCheckBox(panel, -1, "Checkbox", wxPoint(x, y), wxSize(-1, -1), 0, wxDefaultValidator, buf);
1033 }
1034 else if (itemType == "wxListBox")
1035 {
bbcdf8bc 1036 prefix = "ID_LISTBOX";
457814b5
JS
1037 MakeUniqueName("listbox", buf);
1038 res->SetName(buf);
1039 newItem = new wxListBox(panel, -1, wxPoint(x, y), wxSize(-1, -1), 0, NULL, 0, wxDefaultValidator, buf);
1040 }
1041 else if (itemType == "wxRadioBox")
1042 {
5de76427 1043 prefix = "ID_RADIOBOX";
457814b5
JS
1044 MakeUniqueName("radiobox", buf);
1045 res->SetName(buf);
1046 wxString names[] = { "One", "Two" };
1047 newItem = new wxRadioBox(panel, -1, "Radiobox", wxPoint(x, y), wxSize(-1, -1), 2, names, 2,
1048 wxHORIZONTAL, wxDefaultValidator, buf);
1049 res->SetStringValues(new wxStringList("One", "Two", NULL));
1050 }
03f68f12
JS
1051 else if (itemType == "wxRadioButton")
1052 {
5de76427 1053 prefix = "ID_RADIOBUTTON";
03f68f12
JS
1054 MakeUniqueName("radiobutton", buf);
1055 res->SetName(buf);
1056 wxString names[] = { "One", "Two" };
1057 newItem = new wxRadioButton(panel, -1, "Radiobutton", wxPoint(x, y), wxSize(-1, -1),
1058 0, wxDefaultValidator, buf);
1059 }
457814b5
JS
1060 else if (itemType == "wxChoice")
1061 {
5de76427 1062 prefix = "ID_CHOICE";
457814b5
JS
1063 MakeUniqueName("choice", buf);
1064 res->SetName(buf);
1065 newItem = new wxChoice(panel, -1, wxPoint(x, y), wxSize(-1, -1), 0, NULL, 0, wxDefaultValidator, buf);
1066 }
9c331ded
JS
1067 else if (itemType == "wxComboBox")
1068 {
1069 prefix = "ID_COMBOBOX";
1070 MakeUniqueName("combobox", buf);
1071 res->SetName(buf);
1072 newItem = new wxComboBox(panel, -1, "", wxPoint(x, y), wxSize(-1, -1), 0, NULL, wxCB_DROPDOWN, wxDefaultValidator, buf);
1073 }
457814b5
JS
1074 else if (itemType == "wxGroupBox" || itemType == "wxStaticBox")
1075 {
5de76427 1076 prefix = "ID_STATICBOX";
9c331ded 1077 MakeUniqueName("staticbox", buf);
457814b5 1078 res->SetName(buf);
9c331ded 1079 newItem = new wxStaticBox(panel, -1, "Static", wxPoint(x, y), wxSize(200, 200), 0, buf);
457814b5
JS
1080 }
1081 else if (itemType == "wxGauge")
1082 {
5de76427 1083 prefix = "ID_GAUGE";
457814b5
JS
1084 MakeUniqueName("gauge", buf);
1085 res->SetName(buf);
1086 newItem = new wxGauge(panel, -1, 10, wxPoint(x, y), wxSize(80, 30), wxHORIZONTAL, wxDefaultValidator, buf);
1087 }
1088 else if (itemType == "wxSlider")
1089 {
5de76427 1090 prefix = "ID_SLIDER";
457814b5
JS
1091 MakeUniqueName("slider", buf);
1092 res->SetName(buf);
1093 newItem = new wxSlider(panel, -1, 1, 1, 10, wxPoint(x, y), wxSize(120, -1), wxHORIZONTAL, wxDefaultValidator, buf);
1094 }
ae8351fc 1095 else if (itemType == "wxText" || itemType == "wxTextCtrl (single-line)")
457814b5 1096 {
5de76427 1097 prefix = "ID_TEXTCTRL";
ae8351fc 1098 MakeUniqueName("textctrl", buf);
457814b5 1099 res->SetName(buf);
ae8351fc 1100 res->SetType("wxTextCtrl");
457814b5
JS
1101 newItem = new wxTextCtrl(panel, -1, "", wxPoint(x, y), wxSize(120, -1), 0, wxDefaultValidator, buf);
1102 }
ae8351fc 1103 else if (itemType == "wxMultiText" || itemType == "wxTextCtrl (multi-line)")
457814b5 1104 {
5de76427 1105 prefix = "ID_TEXTCTRL";
ae8351fc 1106 MakeUniqueName("textctrl", buf);
457814b5 1107 res->SetName(buf);
ae8351fc
JS
1108 res->SetType("wxTextCtrl");
1109 newItem = new wxTextCtrl(panel, -1, "", wxPoint(x, y), wxSize(120, 100), wxTE_MULTILINE, wxDefaultValidator, buf);
457814b5 1110 }
457814b5
JS
1111 else if (itemType == "wxScrollBar")
1112 {
5de76427 1113 prefix = "ID_SCROLLBAR";
457814b5
JS
1114 MakeUniqueName("scrollbar", buf);
1115 res->SetName(buf);
1116 newItem = new wxScrollBar(panel, -1, wxPoint(x, y), wxSize(140, -1), wxHORIZONTAL, wxDefaultValidator, buf);
1117 }
1118 if (!newItem)
1119 return FALSE;
1120
5de76427
JS
1121 wxString newIdName;
1122 int id = GenerateWindowId(prefix, newIdName);
1123 res->SetId(id);
1124
1125 // This is now guaranteed to be unique, so just add to symbol table
1126 m_symbolTable.AddSymbol(newIdName, id);
1127
457814b5
JS
1128 newItem->PushEventHandler(new wxResourceEditorControlHandler(newItem, newItem));
1129
1130 res->SetStyle(newItem->GetWindowStyleFlag());
1131 AssociateResource(res, newItem);
1132 panelResource->GetChildren().Append(res);
1133
1134 UpdateResourceList();
1135
1136 return TRUE;
1137}
1138
ae8351fc
JS
1139void wxResourceManager::ClearCurrentDialog()
1140{
1141 if (m_editorPanel->m_childWindow)
1142 {
1143 SaveInfoAndDeleteHandler(m_editorPanel->m_childWindow);
1144 DisassociateResource(m_editorPanel->m_childWindow);
1145 DeleteWindow(m_editorPanel->m_childWindow);
1146 m_editorPanel->m_childWindow = NULL;
1147 m_editorPanel->Clear();
1148 }
1149}
1150
03f68f12
JS
1151bool wxResourceManager::TestCurrentDialog(wxWindow* parent)
1152{
1153 if (m_editorPanel->m_childWindow)
1154 {
1155 wxItemResource* item = FindResourceForWindow(m_editorPanel->m_childWindow);
1156 if (!item)
1157 return FALSE;
1158
1159 // Make sure the resources are up-to-date w.r.t. the window
1160 InstantiateResourceFromWindow(item, m_editorPanel->m_childWindow, TRUE);
1161
1162 wxDialog* dialog = new wxDialog;
1163 long oldStyle = item->GetStyle();
1164 bool success = FALSE;
bbcdf8bc 1165// item->SetStyle(wxDEFAULT_DIALOG_STYLE);
03f68f12
JS
1166 if (dialog->LoadFromResource(parent, item->GetName(), & m_resourceTable))
1167 {
1168 dialog->Centre();
1169 dialog->ShowModal();
1170 success = TRUE;
1171 }
bbcdf8bc 1172// item->SetStyle(oldStyle);
03f68f12
JS
1173 return success;
1174 }
1175 return FALSE;
1176}
1177
457814b5
JS
1178// Find the first dialog or panel for which
1179// there is a selected panel item.
ae8351fc 1180wxWindow *wxResourceManager::FindParentOfSelection()
457814b5 1181{
ae8351fc 1182 m_resourceTable.BeginFind();
457814b5 1183 wxNode *node;
ae8351fc 1184 while (node = m_resourceTable.Next())
457814b5
JS
1185 {
1186 wxItemResource *res = (wxItemResource *)node->Data();
1187 wxWindow *win = FindWindowForResource(res);
1188 if (win)
1189 {
1190 wxNode *node1 = win->GetChildren()->First();
1191 while (node1)
1192 {
1193 wxControl *item = (wxControl *)node1->Data();
1194 wxResourceEditorControlHandler *childHandler = (wxResourceEditorControlHandler *)item->GetEventHandler();
1195 if (item->IsKindOf(CLASSINFO(wxControl)) && childHandler->IsSelected())
1196 return win;
1197 node1 = node1->Next();
1198 }
1199 }
1200 }
1201 return NULL;
1202}
1203
1204// Format the panel items according to 'flag'
1205void wxResourceManager::AlignItems(int flag)
1206{
1207 wxWindow *win = FindParentOfSelection();
1208 if (!win)
1209 return;
1210
1211 wxNode *node = GetSelections().First();
1212 if (!node)
1213 return;
1214
1215 wxControl *firstSelection = (wxControl *)node->Data();
1216 if (firstSelection->GetParent() != win)
1217 return;
1218
1219 int firstX, firstY;
1220 int firstW, firstH;
1221 firstSelection->GetPosition(&firstX, &firstY);
1222 firstSelection->GetSize(&firstW, &firstH);
1223 int centreX = (int)(firstX + (firstW / 2));
1224 int centreY = (int)(firstY + (firstH / 2));
1225
1226 while (node = node->Next())
1227 {
1228 wxControl *item = (wxControl *)node->Data();
1229 if (item->GetParent() == win)
1230 {
1231 int x, y, w, h;
1232 item->GetPosition(&x, &y);
1233 item->GetSize(&w, &h);
1234
1235 int newX, newY;
1236
1237 switch (flag)
1238 {
1239 case TOOLBAR_FORMAT_HORIZ:
1240 {
1241 newX = x;
1242 newY = (int)(centreY - (h/2.0));
1243 break;
1244 }
1245 case TOOLBAR_FORMAT_VERT:
1246 {
1247 newX = (int)(centreX - (w/2.0));
1248 newY = y;
1249 break;
1250 }
1251 case TOOLBAR_FORMAT_HORIZ_LEFT_ALIGN:
1252 {
1253 newX = firstX;
1254 newY = y;
1255 break;
1256 }
1257 case TOOLBAR_FORMAT_VERT_TOP_ALIGN:
1258 {
1259 newX = x;
1260 newY = firstY;
1261 break;
1262 }
1263 case TOOLBAR_FORMAT_HORIZ_RIGHT_ALIGN:
1264 {
1265 newX = firstX + firstW - w;
1266 newY = y;
1267 break;
1268 }
1269 case TOOLBAR_FORMAT_VERT_BOT_ALIGN:
1270 {
1271 newX = x;
1272 newY = firstY + firstH - h;
1273 break;
1274 }
1275 default:
1276 newX = x; newY = y;
1277 break;
1278 }
1279
1280 item->SetSize(newX, newY, w, h);
1281 }
1282 }
1283 win->Refresh();
1284}
1285
1286// Copy the first image's size to subsequent images
ae8351fc 1287void wxResourceManager::CopySize()
457814b5
JS
1288{
1289 wxWindow *win = FindParentOfSelection();
1290 if (!win)
1291 return;
1292
1293 wxNode *node = GetSelections().First();
1294 if (!node)
1295 return;
1296
1297 wxControl *firstSelection = (wxControl *)node->Data();
1298 if (firstSelection->GetParent() != win)
1299 return;
1300
1301 int firstX, firstY;
1302 int firstW, firstH;
1303 firstSelection->GetPosition(&firstX, &firstY);
1304 firstSelection->GetSize(&firstW, &firstH);
1305 int centreX = (int)(firstX + (firstW / 2));
1306 int centreY = (int)(firstY + (firstH / 2));
1307
1308 while (node = node->Next())
1309 {
1310 wxControl *item = (wxControl *)node->Data();
1311 if (item->GetParent() == win)
1312 item->SetSize(-1, -1, firstW, firstH);
1313 }
1314 win->Refresh();
1315}
1316
1317void wxResourceManager::ToBackOrFront(bool toBack)
1318{
1319 wxWindow *win = FindParentOfSelection();
1320 if (!win)
1321 return;
1322 wxItemResource *winResource = FindResourceForWindow(win);
1323
1324 wxNode *node = GetSelections().First();
1325 while (node)
1326 {
1327 wxControl *item = (wxControl *)node->Data();
1328 wxItemResource *itemResource = FindResourceForWindow(item);
1329 if (item->GetParent() == win)
1330 {
1331 win->GetChildren()->DeleteObject(item);
1332 if (winResource)
1333 winResource->GetChildren().DeleteObject(itemResource);
1334 if (toBack)
1335 {
1336 win->GetChildren()->Insert(item);
1337 if (winResource)
1338 winResource->GetChildren().Insert(itemResource);
1339 }
1340 else
1341 {
1342 win->GetChildren()->Append(item);
1343 if (winResource)
1344 winResource->GetChildren().Append(itemResource);
1345 }
1346 }
1347 node = node->Next();
1348 }
1349// win->Refresh();
1350}
1351
1352void wxResourceManager::AddSelection(wxWindow *win)
1353{
ae8351fc
JS
1354 if (!m_selections.Member(win))
1355 m_selections.Append(win);
457814b5
JS
1356}
1357
1358void wxResourceManager::RemoveSelection(wxWindow *win)
1359{
ae8351fc 1360 m_selections.DeleteObject(win);
457814b5
JS
1361}
1362
1363// Need to search through resource table removing this from
1364// any resource which has this as a parent.
1365bool wxResourceManager::RemoveResourceFromParent(wxItemResource *res)
1366{
ae8351fc 1367 m_resourceTable.BeginFind();
457814b5 1368 wxNode *node;
ae8351fc 1369 while (node = m_resourceTable.Next())
457814b5
JS
1370 {
1371 wxItemResource *thisRes = (wxItemResource *)node->Data();
1372 if (thisRes->GetChildren().Member(res))
1373 {
1374 thisRes->GetChildren().DeleteObject(res);
1375 return TRUE;
1376 }
1377 }
1378 return FALSE;
1379}
1380
1381bool wxResourceManager::DeleteResource(wxItemResource *res)
1382{
1383 if (!res)
1384 return FALSE;
1385
1386 RemoveResourceFromParent(res);
1387
1388 wxNode *node = res->GetChildren().First();
1389 while (node)
1390 {
1391 wxNode *next = node->Next();
1392 wxItemResource *child = (wxItemResource *)node->Data();
1393 DeleteResource(child);
1394 node = next;
1395 }
1396
1397 // If this is a button or message resource, delete the
1398 // associate bitmap resource if not being used.
1399 wxString resType(res->GetType());
1400
ae8351fc 1401 if ((resType == "wxMessage" || resType == "wxStaticBitmap" || resType == "wxButton" || resType == "wxBitmapButton") && res->GetValue4())
457814b5
JS
1402 {
1403 PossiblyDeleteBitmapResource(res->GetValue4());
1404 }
1405
5de76427
JS
1406 // Remove symbol from table if appropriate
1407 if (!IsSymbolUsed(res, res->GetId()))
1408 {
1409 m_symbolTable.RemoveSymbol(res->GetId());
1410 }
1411
ae8351fc 1412 m_resourceTable.Delete(res->GetName());
457814b5
JS
1413 delete res;
1414 Modify(TRUE);
1415 return TRUE;
1416}
1417
ae8351fc 1418bool wxResourceManager::DeleteResource(wxWindow *win)
457814b5
JS
1419{
1420 if (win->IsKindOf(CLASSINFO(wxControl)))
1421 {
1422 // Deselect and refresh window in case we leave selection
1423 // handles behind
1424 wxControl *item = (wxControl *)win;
1425 wxResourceEditorControlHandler *childHandler = (wxResourceEditorControlHandler *)item->GetEventHandler();
1426 if (childHandler->IsSelected())
1427 {
1428 RemoveSelection(item);
1429 childHandler->SelectItem(FALSE);
1430 item->GetParent()->Refresh();
1431 }
1432 }
1433
1434 wxItemResource *res = FindResourceForWindow(win);
1435
ae8351fc 1436 DisassociateResource(res);
457814b5
JS
1437 DeleteResource(res);
1438 UpdateResourceList();
1439
457814b5
JS
1440 return TRUE;
1441}
1442
1443// Will eventually have bitmap type information, for different
1444// kinds of bitmap.
1445char *wxResourceManager::AddBitmapResource(char *filename)
1446{
1447 wxItemResource *resource = FindBitmapResourceByFilename(filename);
1448 if (!resource)
1449 {
1450 char buf[256];
1451 MakeUniqueName("bitmap", buf);
1452 resource = new wxItemResource;
1453 resource->SetType("wxBitmap");
1454 resource->SetName(buf);
1455
1456 // A bitmap resource has one or more children, specifying
1457 // alternative bitmaps.
1458 wxItemResource *child = new wxItemResource;
1459 child->SetType("wxBitmap");
1460 child->SetName(filename);
1461 child->SetValue1(wxBITMAP_TYPE_BMP);
1462 child->SetValue2(RESOURCE_PLATFORM_ANY);
1463 child->SetValue3(0); // Depth
1464 child->SetSize(0,0,0,0);
1465 resource->GetChildren().Append(child);
1466
ae8351fc 1467 m_resourceTable.AddResource(resource);
457814b5
JS
1468
1469 UpdateResourceList();
1470 }
1471 if (resource)
1472 return resource->GetName();
1473 else
1474 return NULL;
1475}
1476
1477 // Delete the bitmap resource if it isn't being used by another resource.
1478void wxResourceManager::PossiblyDeleteBitmapResource(char *resourceName)
1479{
1480 if (!IsBitmapResourceUsed(resourceName))
1481 {
ae8351fc 1482 wxItemResource *res = m_resourceTable.FindResource(resourceName);
457814b5
JS
1483 DeleteResource(res);
1484 UpdateResourceList();
1485 }
1486}
1487
1488bool wxResourceManager::IsBitmapResourceUsed(char *resourceName)
1489{
ae8351fc 1490 m_resourceTable.BeginFind();
457814b5 1491 wxNode *node;
ae8351fc 1492 while (node = m_resourceTable.Next())
457814b5
JS
1493 {
1494 wxItemResource *res = (wxItemResource *)node->Data();
1495 wxString resType(res->GetType());
1496 if (resType == "wxDialog")
1497 {
1498 wxNode *node1 = res->GetChildren().First();
1499 while (node1)
1500 {
1501 wxItemResource *child = (wxItemResource *)node1->Data();
1502 wxString childResType(child->GetType());
1503
1504 if ((childResType == "wxMessage" || childResType == "wxButton") &&
1505 child->GetValue4() &&
1506 (strcmp(child->GetValue4(), resourceName) == 0))
1507 return TRUE;
1508 node1 = node1->Next();
1509 }
1510 }
1511 }
1512 return FALSE;
1513}
1514
1515// Given a wxButton or wxMessage, find the corresponding bitmap filename.
1516char *wxResourceManager::FindBitmapFilenameForResource(wxItemResource *resource)
1517{
1518 if (!resource || !resource->GetValue4())
1519 return NULL;
ae8351fc 1520 wxItemResource *bitmapResource = m_resourceTable.FindResource(resource->GetValue4());
457814b5
JS
1521 if (!bitmapResource)
1522 return NULL;
1523
1524 wxNode *node = bitmapResource->GetChildren().First();
1525 while (node)
1526 {
1527 // Eventually augment this to return a bitmap of the right kind or something...
1528 // Maybe the root of the filename remains the same, so it doesn't matter which we
1529 // pick up. Otherwise how do we specify multiple filenames... too boring...
1530 wxItemResource *child = (wxItemResource *)node->Data();
1531 return child->GetName();
1532
1533 node = node->Next();
1534 }
1535 return NULL;
1536}
1537
1538wxItemResource *wxResourceManager::FindBitmapResourceByFilename(char *filename)
1539{
ae8351fc 1540 m_resourceTable.BeginFind();
457814b5 1541 wxNode *node;
ae8351fc 1542 while (node = m_resourceTable.Next())
457814b5
JS
1543 {
1544 wxItemResource *res = (wxItemResource *)node->Data();
1545 wxString resType(res->GetType());
1546 if (resType == "wxBitmap")
1547 {
1548 wxNode *node1 = res->GetChildren().First();
1549 while (node1)
1550 {
1551 wxItemResource *child = (wxItemResource *)node1->Data();
1552 if (child->GetName() && (strcmp(child->GetName(), filename) == 0))
1553 return res;
1554 node1 = node1->Next();
1555 }
1556 }
1557 }
1558 return NULL;
1559}
1560
5de76427
JS
1561// Is this window identifier symbol in use?
1562// Let's assume that we can't have 2 names for the same integer id.
1563// Therefore we can tell by the integer id whether the symbol is
1564// in use.
1565bool wxResourceManager::IsSymbolUsed(wxItemResource* thisResource, wxWindowID id)
1566{
1567 m_resourceTable.BeginFind();
1568 wxNode *node;
1569 while (node = m_resourceTable.Next())
1570 {
1571 wxItemResource *res = (wxItemResource *)node->Data();
5de76427
JS
1572
1573 wxString resType(res->GetType());
1574 if (resType == "wxDialog" || resType == "wxDialogBox" || resType == "wxPanel")
1575 {
bbcdf8bc
JS
1576 if ((res != thisResource) && (res->GetId() == id))
1577 return TRUE;
1578
5de76427
JS
1579 wxNode *node1 = res->GetChildren().First();
1580 while (node1)
1581 {
1582 wxItemResource *child = (wxItemResource *)node1->Data();
1583 if ((child != thisResource) && (child->GetId() == id))
1584 return TRUE;
1585 node1 = node1->Next();
1586 }
1587 }
1588 }
1589 return FALSE;
1590}
1591
1592// Is this window identifier compatible with the given name? (i.e.
1593// does it already exist under a different name)
1594bool wxResourceManager::IsIdentifierOK(const wxString& name, wxWindowID id)
1595{
1596 if (m_symbolTable.SymbolExists(name))
1597 {
1598 int foundId = m_symbolTable.GetIdForSymbol(name);
1599 if (foundId != id)
1600 return FALSE;
1601 }
1602 return TRUE;
1603}
1604
1605// Change all integer ids that match oldId, to newId.
1606// This is necessary if an id is changed for one resource - all resources
1607// must be changed.
1608void wxResourceManager::ChangeIds(int oldId, int newId)
1609{
1610 m_resourceTable.BeginFind();
1611 wxNode *node;
1612 while (node = m_resourceTable.Next())
1613 {
1614 wxItemResource *res = (wxItemResource *)node->Data();
5de76427
JS
1615
1616 wxString resType(res->GetType());
1617 if (resType == "wxDialog" || resType == "wxDialogBox" || resType == "wxPanel")
1618 {
bbcdf8bc
JS
1619 if (res->GetId() == oldId)
1620 res->SetId(newId);
1621
5de76427
JS
1622 wxNode *node1 = res->GetChildren().First();
1623 while (node1)
1624 {
1625 wxItemResource *child = (wxItemResource *)node1->Data();
1626 if (child->GetId() == oldId)
1627 child->SetId(newId);
1628
1629 node1 = node1->Next();
1630 }
1631 }
1632 }
1633}
1634
bbcdf8bc
JS
1635// If any resource ids were missing (or their symbol was missing),
1636// repair them i.e. give them new ids. Returns TRUE if any resource
1637// needed repairing.
1638bool wxResourceManager::RepairResourceIds()
1639{
1640 bool repaired = FALSE;
1641
1642 m_resourceTable.BeginFind();
1643 wxNode *node;
1644 while (node = m_resourceTable.Next())
1645 {
1646 wxItemResource *res = (wxItemResource *)node->Data();
1647 wxString resType(res->GetType());
1648 if (resType == "wxDialog" || resType == "wxDialogBox" || resType == "wxPanel")
1649 {
1650
1651 if ( (res->GetId() == 0) || ((res->GetId() > 0) && !m_symbolTable.IdExists(res->GetId())) )
1652 {
1653 wxString newSymbolName;
1654 int newId = GenerateWindowId("ID_DIALOG", newSymbolName) ;
1655
1656 if (res->GetId() == 0)
1657 {
1658 res->SetId(newId);
1659 m_symbolTable.AddSymbol(newSymbolName, newId);
1660 }
1661 else
1662 {
1663 m_symbolTable.AddSymbol(newSymbolName, res->GetId());
1664 }
1665
1666 repaired = TRUE;
1667 }
1668
1669 wxNode *node1 = res->GetChildren().First();
1670 while (node1)
1671 {
1672 wxItemResource *child = (wxItemResource *)node1->Data();
1673
1674 if ( (child->GetId() == 0) || ((child->GetId() > 0) && !m_symbolTable.IdExists(child->GetId())) )
1675 {
1676 wxString newSymbolName;
1677 int newId = GenerateWindowId("ID_CONTROL", newSymbolName) ;
1678
1679 if (child->GetId() == 0)
1680 {
1681 child->SetId(newId);
1682 m_symbolTable.AddSymbol(newSymbolName, newId);
1683 }
1684 else
1685 {
1686 m_symbolTable.AddSymbol(newSymbolName, child->GetId());
1687 }
1688
1689 repaired = TRUE;
1690 }
1691
1692 node1 = node1->Next();
1693 }
1694 }
1695 }
1696 return repaired;
1697}
1698
1699
457814b5
JS
1700 // Deletes 'win' and creates a new window from the resource that
1701 // was associated with it. E.g. if you can't change properties on the
1702 // fly, you'll need to delete the window and create it again.
1703wxWindow *wxResourceManager::RecreateWindowFromResource(wxWindow *win, wxWindowPropertyInfo *info)
1704{
1705 wxItemResource *resource = FindResourceForWindow(win);
1706
1707 // Put the current window properties into the wxItemResource object
1708
1709 wxWindowPropertyInfo *newInfo = NULL;
1710 if (!info)
1711 {
ae8351fc 1712 newInfo = CreatePropertyInfoForWindow(win);
457814b5
JS
1713 info = newInfo;
1714 }
1715
1716 info->InstantiateResource(resource);
1717
1718 wxWindow *newWin = NULL;
1719 wxWindow *parent = win->GetParent();
1720
1721 if (win->IsKindOf(CLASSINFO(wxPanel)))
1722 {
457814b5
JS
1723 Edit(resource);
1724 newWin = FindWindowForResource(resource);
1725 }
1726 else
1727 {
ae8351fc 1728 DisassociateResource(resource);
9c331ded
JS
1729 if (win->GetEventHandler() != win)
1730 win->PopEventHandler(TRUE);
1731
ae8351fc
JS
1732 DeleteWindow(win);
1733 newWin = m_resourceTable.CreateItem((wxPanel *)parent, resource);
9c331ded 1734 newWin->PushEventHandler(new wxResourceEditorControlHandler((wxControl*) newWin, (wxControl*) newWin));
457814b5
JS
1735 AssociateResource(resource, newWin);
1736 UpdateResourceList();
1737 }
1738
1739 if (info)
1740 info->SetPropertyWindow(newWin);
1741
1742 if (newInfo)
1743 delete newInfo;
1744
1745 return newWin;
1746}
1747
1748// Delete resource highlighted in the listbox
ae8351fc 1749bool wxResourceManager::DeleteSelection()
457814b5 1750{
ae8351fc 1751 int sel = m_editorResourceTree->GetSelection();
03f68f12 1752 if (sel != 0)
457814b5 1753 {
ae8351fc 1754 wxItemResource *res = (wxItemResource *)m_editorResourceTree->GetItemData(sel);
457814b5 1755 wxWindow *win = FindWindowForResource(res);
ae8351fc 1756 if (win)
457814b5 1757 {
ae8351fc
JS
1758 DeleteResource(win);
1759 DeleteWindow(win);
1760 UpdateResourceList();
1761 Modify(TRUE);
457814b5 1762 }
ae8351fc 1763 return TRUE;
457814b5
JS
1764 }
1765
1766 return FALSE;
1767}
1768
1769// Delete resource highlighted in the listbox
ae8351fc 1770bool wxResourceManager::RecreateSelection()
457814b5
JS
1771{
1772 wxNode *node = GetSelections().First();
1773 while (node)
1774 {
1775 wxControl *item = (wxControl *)node->Data();
1776 wxResourceEditorControlHandler *childHandler = (wxResourceEditorControlHandler *)item->GetEventHandler();
1777 wxNode *next = node->Next();
1778 childHandler->SelectItem(FALSE);
1779
1780 RemoveSelection(item);
1781
1782 RecreateWindowFromResource(item);
1783
1784 node = next;
1785 }
1786 return TRUE;
1787}
1788
1789bool wxResourceManager::EditDialog(wxDialog *dialog, wxWindow *parent)
1790{
1791 return FALSE;
1792}
1793
457814b5
JS
1794// Ensures that all currently shown windows are saved to resources,
1795// e.g. just before writing to a .wxr file.
ae8351fc 1796bool wxResourceManager::InstantiateAllResourcesFromWindows()
457814b5 1797{
ae8351fc 1798 m_resourceTable.BeginFind();
457814b5 1799 wxNode *node;
ae8351fc 1800 while (node = m_resourceTable.Next())
457814b5
JS
1801 {
1802 wxItemResource *res = (wxItemResource *)node->Data();
1803 wxString resType(res->GetType());
1804
1805 if (resType == "wxDialog")
1806 {
1807 wxWindow *win = (wxWindow *)FindWindowForResource(res);
1808 if (win)
1809 InstantiateResourceFromWindow(res, win, TRUE);
1810 }
1811 else if (resType == "wxPanel")
1812 {
1813 wxWindow *win = (wxWindow *)FindWindowForResource(res);
1814 if (win)
1815 InstantiateResourceFromWindow(res, win, TRUE);
1816 }
1817 }
1818 return TRUE;
1819}
1820
1821bool wxResourceManager::InstantiateResourceFromWindow(wxItemResource *resource, wxWindow *window, bool recurse)
1822{
ae8351fc 1823 wxWindowPropertyInfo *info = CreatePropertyInfoForWindow(window);
457814b5
JS
1824 info->SetResource(resource);
1825 info->InstantiateResource(resource);
1826 delete info;
1827
1828 if (recurse)
1829 {
1830 wxNode *node = resource->GetChildren().First();
1831 while (node)
1832 {
1833 wxItemResource *child = (wxItemResource *)node->Data();
1834 wxWindow *childWindow = FindWindowForResource(child);
1835
1836 if (!childWindow)
1837 {
1838 char buf[200];
1839 sprintf(buf, "Could not find window %s", child->GetName());
1840 wxMessageBox(buf, "Dialog Editor problem", wxOK);
1841 }
1842 else
1843 InstantiateResourceFromWindow(child, childWindow, recurse);
1844 node = node->Next();
1845 }
1846 }
1847
1848 return TRUE;
1849}
1850
ae8351fc
JS
1851// Create a window information object for the give window
1852wxWindowPropertyInfo *wxResourceManager::CreatePropertyInfoForWindow(wxWindow *win)
1853{
1854 wxWindowPropertyInfo *info = NULL;
1855 if (win->IsKindOf(CLASSINFO(wxScrollBar)))
1856 {
1857 info = new wxScrollBarPropertyInfo(win);
1858 }
1859 else if (win->IsKindOf(CLASSINFO(wxStaticBox)))
1860 {
1861 info = new wxGroupBoxPropertyInfo(win);
1862 }
1863 else if (win->IsKindOf(CLASSINFO(wxCheckBox)))
1864 {
1865 info = new wxCheckBoxPropertyInfo(win);
1866 }
1867 else if (win->IsKindOf(CLASSINFO(wxSlider)))
1868 {
1869 info = new wxSliderPropertyInfo(win);
1870 }
1871 else if (win->IsKindOf(CLASSINFO(wxGauge)))
1872 {
1873 info = new wxGaugePropertyInfo(win);
1874 }
1875 else if (win->IsKindOf(CLASSINFO(wxListBox)))
1876 {
1877 info = new wxListBoxPropertyInfo(win);
1878 }
1879 else if (win->IsKindOf(CLASSINFO(wxRadioBox)))
1880 {
1881 info = new wxRadioBoxPropertyInfo(win);
1882 }
03f68f12
JS
1883 else if (win->IsKindOf(CLASSINFO(wxRadioButton)))
1884 {
1885 info = new wxRadioButtonPropertyInfo(win);
1886 }
ae8351fc
JS
1887 else if (win->IsKindOf(CLASSINFO(wxChoice)))
1888 {
1889 info = new wxChoicePropertyInfo(win);
1890 }
9c331ded
JS
1891 else if (win->IsKindOf(CLASSINFO(wxComboBox)))
1892 {
1893 info = new wxComboBoxPropertyInfo(win);
1894 }
ae8351fc
JS
1895 else if (win->IsKindOf(CLASSINFO(wxButton)))
1896 {
1897 info = new wxButtonPropertyInfo(win);
1898 }
1899 else if (win->IsKindOf(CLASSINFO(wxBitmapButton)))
1900 {
1901 info = new wxBitmapButtonPropertyInfo(win);
1902 }
1903 else if (win->IsKindOf(CLASSINFO(wxStaticText)))
1904 {
1905 info = new wxStaticTextPropertyInfo(win);
1906 }
1907 else if (win->IsKindOf(CLASSINFO(wxStaticBitmap)))
1908 {
1909 info = new wxStaticBitmapPropertyInfo(win);
1910 }
1911 else if (win->IsKindOf(CLASSINFO(wxTextCtrl)))
1912 {
1913 info = new wxTextPropertyInfo(win);
1914 }
1915 else if (win->IsKindOf(CLASSINFO(wxPanel)))
1916 {
1917 info = new wxPanelPropertyInfo(win);
1918 }
1919 else
1920 {
1921 info = new wxWindowPropertyInfo(win);
1922 }
1923 return info;
1924}
1925
1926// Edit the given window
1927void wxResourceManager::EditWindow(wxWindow *win)
1928{
1929 wxWindowPropertyInfo *info = CreatePropertyInfoForWindow(win);
1930 if (info)
1931 {
1932 info->SetResource(FindResourceForWindow(win));
1933 wxString str("Editing ");
1934 str += win->GetClassInfo()->GetClassName();
1935 str += ": ";
1936 if (win->GetName() != "")
1937 str += win->GetName();
1938 else
1939 str += "properties";
1940 info->Edit(NULL, str);
1941 }
1942}
1943
5de76427
JS
1944// Generate a window id and a first stab at a name
1945int wxResourceManager::GenerateWindowId(const wxString& prefix, wxString& idName)
1946{
1947 m_symbolIdCounter ++;
1948 while (m_symbolTable.IdExists(m_symbolIdCounter))
1949 m_symbolIdCounter ++;
1950
1951 int nameId = m_symbolIdCounter;
1952
1953 wxString str;
1954 str.Printf("%d", nameId);
1955 idName = prefix + str;
1956
1957 while (m_symbolTable.SymbolExists(idName))
1958 {
1959 nameId ++;
1960 str.Printf("%d", nameId);
1961 idName = prefix + str;
1962 }
1963
1964 return m_symbolIdCounter;
1965}
1966
457814b5
JS
1967
1968/*
1969 * Resource editor frame
1970 */
ae8351fc
JS
1971
1972IMPLEMENT_CLASS(wxResourceEditorFrame, wxFrame)
1973
1974BEGIN_EVENT_TABLE(wxResourceEditorFrame, wxFrame)
1975 EVT_MENU(wxID_NEW, wxResourceEditorFrame::OnNew)
1976 EVT_MENU(RESED_NEW_DIALOG, wxResourceEditorFrame::OnNewDialog)
1977 EVT_MENU(wxID_OPEN, wxResourceEditorFrame::OnOpen)
1978 EVT_MENU(RESED_CLEAR, wxResourceEditorFrame::OnClear)
1979 EVT_MENU(wxID_SAVE, wxResourceEditorFrame::OnSave)
1980 EVT_MENU(wxID_SAVEAS, wxResourceEditorFrame::OnSaveAs)
1981 EVT_MENU(wxID_EXIT, wxResourceEditorFrame::OnExit)
1982 EVT_MENU(wxID_ABOUT, wxResourceEditorFrame::OnAbout)
1983 EVT_MENU(RESED_CONTENTS, wxResourceEditorFrame::OnContents)
1984 EVT_MENU(RESED_DELETE, wxResourceEditorFrame::OnDeleteSelection)
1985 EVT_MENU(RESED_RECREATE, wxResourceEditorFrame::OnRecreateSelection)
1986 EVT_MENU(RESED_TEST, wxResourceEditorFrame::OnTest)
1987END_EVENT_TABLE()
1988
1989wxResourceEditorFrame::wxResourceEditorFrame(wxResourceManager *resMan, wxFrame *parent, const wxString& title,
1990 const wxPoint& pos, const wxSize& size, long style, const wxString& name):
1991 wxFrame(parent, -1, title, pos, size, style, name)
457814b5
JS
1992{
1993 manager = resMan;
1994}
1995
ae8351fc 1996wxResourceEditorFrame::~wxResourceEditorFrame()
457814b5
JS
1997{
1998}
1999
b127f301 2000void wxResourceEditorFrame::OnNew(wxCommandEvent& WXUNUSED(event))
457814b5 2001{
457814b5 2002 manager->New(FALSE);
ae8351fc
JS
2003}
2004
b127f301 2005void wxResourceEditorFrame::OnNewDialog(wxCommandEvent& WXUNUSED(event))
ae8351fc 2006{
457814b5 2007 manager->CreateNewPanel();
ae8351fc
JS
2008}
2009
b127f301 2010void wxResourceEditorFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
ae8351fc 2011{
457814b5 2012 manager->New(TRUE);
ae8351fc
JS
2013}
2014
b127f301 2015void wxResourceEditorFrame::OnClear(wxCommandEvent& WXUNUSED(event))
ae8351fc 2016{
457814b5 2017 manager->Clear(TRUE, FALSE);
ae8351fc
JS
2018}
2019
b127f301 2020void wxResourceEditorFrame::OnSave(wxCommandEvent& WXUNUSED(event))
ae8351fc 2021{
457814b5 2022 manager->Save();
ae8351fc
JS
2023}
2024
b127f301 2025void wxResourceEditorFrame::OnSaveAs(wxCommandEvent& WXUNUSED(event))
ae8351fc 2026{
457814b5 2027 manager->SaveAs();
ae8351fc
JS
2028}
2029
b127f301 2030void wxResourceEditorFrame::OnExit(wxCommandEvent& WXUNUSED(event))
ae8351fc 2031{
457814b5
JS
2032 manager->Clear(TRUE, FALSE) ;
2033 this->Close();
ae8351fc
JS
2034}
2035
b127f301 2036void wxResourceEditorFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
ae8351fc 2037{
457814b5
JS
2038 char buf[300];
2039 sprintf(buf, "wxWindows Dialog Editor %.1f\nAuthor: Julian Smart J.Smart@ed.ac.uk\nJulian Smart (c) 1996", wxDIALOG_EDITOR_VERSION);
ae8351fc
JS
2040 wxMessageBox(buf, "About Dialog Editor", wxOK|wxCENTRE);
2041}
2042
b127f301 2043void wxResourceEditorFrame::OnTest(wxCommandEvent& WXUNUSED(event))
ae8351fc 2044{
03f68f12 2045 manager->TestCurrentDialog(this);
ae8351fc
JS
2046}
2047
b127f301 2048void wxResourceEditorFrame::OnContents(wxCommandEvent& WXUNUSED(event))
ae8351fc 2049{
d0fff5cb 2050#ifdef __WXMSW__
457814b5 2051 wxBeginBusyCursor();
ae8351fc
JS
2052 manager->GetHelpController()->LoadFile();
2053 manager->GetHelpController()->DisplayContents();
457814b5 2054 wxEndBusyCursor();
b127f301 2055#endif
ae8351fc
JS
2056}
2057
b127f301 2058void wxResourceEditorFrame::OnDeleteSelection(wxCommandEvent& WXUNUSED(event))
ae8351fc 2059{
457814b5 2060 manager->DeleteSelection();
ae8351fc
JS
2061}
2062
b127f301 2063void wxResourceEditorFrame::OnRecreateSelection(wxCommandEvent& WXUNUSED(event))
ae8351fc 2064{
457814b5 2065 manager->RecreateSelection();
457814b5
JS
2066}
2067
ae8351fc 2068bool wxResourceEditorFrame::OnClose()
457814b5
JS
2069{
2070 if (manager->Modified())
2071 {
457814b5
JS
2072 if (!manager->Clear(TRUE, FALSE))
2073 return FALSE;
2074 }
2075
2076 if (!Iconized())
2077 {
2078 int w, h;
2079 GetSize(&w, &h);
ae8351fc
JS
2080 manager->m_resourceEditorWindowSize.width = w;
2081 manager->m_resourceEditorWindowSize.height = h;
457814b5
JS
2082
2083 int x, y;
2084 GetPosition(&x, &y);
2085
ae8351fc
JS
2086 manager->m_resourceEditorWindowSize.x = x;
2087 manager->m_resourceEditorWindowSize.y = y;
457814b5
JS
2088 }
2089 manager->SetEditorFrame(NULL);
2090 manager->SetEditorToolBar(NULL);
457814b5
JS
2091
2092 return TRUE;
2093}
2094
2095/*
ae8351fc 2096 * Resource editor window that contains the dialog/panel being edited
457814b5 2097 */
ae8351fc
JS
2098
2099BEGIN_EVENT_TABLE(wxResourceEditorScrolledWindow, wxScrolledWindow)
2100 EVT_SCROLL(wxResourceEditorScrolledWindow::OnScroll)
2101 EVT_PAINT(wxResourceEditorScrolledWindow::OnPaint)
2102END_EVENT_TABLE()
2103
2104wxResourceEditorScrolledWindow::wxResourceEditorScrolledWindow(wxWindow *parent, const wxPoint& pos, const wxSize& size,
2105 long style):
2106 wxScrolledWindow(parent, -1, pos, size, style)
457814b5 2107{
ae8351fc
JS
2108 m_marginX = 10;
2109 m_marginY = 40;
2110 m_childWindow = NULL;
457814b5
JS
2111}
2112
ae8351fc 2113wxResourceEditorScrolledWindow::~wxResourceEditorScrolledWindow()
457814b5
JS
2114{
2115}
2116
ae8351fc 2117void wxResourceEditorScrolledWindow::OnScroll(wxScrollEvent& event)
457814b5 2118{
ae8351fc 2119 wxScrolledWindow::OnScroll(event);
457814b5 2120
ae8351fc
JS
2121 int x, y;
2122 ViewStart(& x, & y);
2123
2124 if (m_childWindow)
2125 m_childWindow->Move(m_marginX + (- x * 10), m_marginY + (- y * 10));
2126}
2127
b127f301 2128void wxResourceEditorScrolledWindow::OnPaint(wxPaintEvent& WXUNUSED(event))
ae8351fc
JS
2129{
2130 wxPaintDC dc(this);
2131
2132 DrawTitle(dc);
2133}
2134
2135void wxResourceEditorScrolledWindow::DrawTitle(wxDC& dc)
2136{
2137 if (m_childWindow)
2138 {
2139 wxItemResource* res = wxResourceManager::GetCurrentResourceManager()->FindResourceForWindow(m_childWindow);
2140 if (res)
2141 {
2142 wxString str(res->GetTitle());
2143 int x, y;
2144 ViewStart(& x, & y);
2145
2146 wxFont font(10, wxSWISS, wxNORMAL, wxBOLD);
2147 dc.SetFont(font);
2148 dc.SetBackgroundMode(wxTRANSPARENT);
2149 dc.SetTextForeground(wxColour(0, 0, 0));
2150
2151 long w, h;
2152 dc.GetTextExtent(str, & w, & h);
2153
2154 dc.DrawText(str, m_marginX + (- x * 10), m_marginY + (- y * 10) - h - 5);
2155 }
2156 }
457814b5
JS
2157}
2158
2159// Popup menu callback
2160void ObjectMenuProc(wxMenu& menu, wxCommandEvent& event)
2161{
2162 wxWindow *data = (wxWindow *)menu.GetClientData();
2163 if (!data)
2164 return;
2165
2166 switch (event.GetInt())
2167 {
2168 case OBJECT_MENU_EDIT:
2169 {
ae8351fc 2170 wxResourceManager::GetCurrentResourceManager()->EditWindow(data);
457814b5
JS
2171 break;
2172 }
2173 case OBJECT_MENU_DELETE:
2174 {
ae8351fc
JS
2175 wxResourceManager::GetCurrentResourceManager()->SaveInfoAndDeleteHandler(data);
2176 wxResourceManager::GetCurrentResourceManager()->DeleteResource(data);
2177 wxResourceManager::GetCurrentResourceManager()->DeleteWindow(data);
457814b5
JS
2178 break;
2179 }
2180 default:
2181 break;
2182 }
2183}
2184
457814b5
JS
2185/*
2186 * Main toolbar
2187 *
2188 */
2189
9d3221ab
RR
2190#ifdef __WXGTK__ // I don't dare to delete it...
2191
2192BEGIN_EVENT_TABLE(EditorToolBar, wxToolBar)
2193END_EVENT_TABLE()
2194
2195#else
2196
ae8351fc 2197BEGIN_EVENT_TABLE(EditorToolBar, wxToolBar)
457814b5
JS
2198 EVT_PAINT(EditorToolBar::OnPaint)
2199END_EVENT_TABLE()
2200
9d3221ab
RR
2201#endif
2202
ae8351fc 2203EditorToolBar::EditorToolBar(wxFrame *frame, const wxPoint& pos, const wxSize& size,
f449ef69
JS
2204 long style):
2205 wxToolBar(frame, -1, pos, size, style)
457814b5
JS
2206{
2207}
2208
2209bool EditorToolBar::OnLeftClick(int toolIndex, bool toggled)
2210{
ae8351fc
JS
2211 wxResourceManager *manager = wxResourceManager::GetCurrentResourceManager();
2212
457814b5
JS
2213 switch (toolIndex)
2214 {
2215 case TOOLBAR_LOAD_FILE:
2216 {
2217 manager->New(TRUE);
2218 break;
2219 }
2220 case TOOLBAR_NEW:
2221 {
ae8351fc 2222 manager->CreateNewPanel();
457814b5
JS
2223 break;
2224 }
2225 case TOOLBAR_SAVE_FILE:
2226 {
2227 manager->Save();
2228 break;
2229 }
2230 case TOOLBAR_HELP:
2231 {
d0fff5cb 2232#ifdef __WXMSW__
457814b5 2233 wxBeginBusyCursor();
ae8351fc
JS
2234 manager->GetHelpController()->LoadFile();
2235 manager->GetHelpController()->DisplayContents();
457814b5 2236 wxEndBusyCursor();
b127f301 2237#endif
457814b5
JS
2238 break;
2239 }
2240 case TOOLBAR_FORMAT_HORIZ:
2241 {
2242 manager->AlignItems(TOOLBAR_FORMAT_HORIZ);
2243 break;
2244 }
2245 case TOOLBAR_FORMAT_HORIZ_LEFT_ALIGN:
2246 {
2247 manager->AlignItems(TOOLBAR_FORMAT_HORIZ_LEFT_ALIGN);
2248 break;
2249 }
2250 case TOOLBAR_FORMAT_HORIZ_RIGHT_ALIGN:
2251 {
2252 manager->AlignItems(TOOLBAR_FORMAT_HORIZ_RIGHT_ALIGN);
2253 break;
2254 }
2255 case TOOLBAR_FORMAT_VERT:
2256 {
2257 manager->AlignItems(TOOLBAR_FORMAT_VERT);
2258 break;
2259 }
2260 case TOOLBAR_FORMAT_VERT_TOP_ALIGN:
2261 {
2262 manager->AlignItems(TOOLBAR_FORMAT_VERT_TOP_ALIGN);
2263 break;
2264 }
2265 case TOOLBAR_FORMAT_VERT_BOT_ALIGN:
2266 {
2267 manager->AlignItems(TOOLBAR_FORMAT_VERT_BOT_ALIGN);
2268 break;
2269 }
2270 case TOOLBAR_COPY_SIZE:
2271 {
2272 manager->CopySize();
2273 break;
2274 }
2275 case TOOLBAR_TO_BACK:
2276 {
2277 manager->ToBackOrFront(TRUE);
2278 break;
2279 }
2280 case TOOLBAR_TO_FRONT:
2281 {
2282 manager->ToBackOrFront(FALSE);
2283 break;
2284 }
2285 default:
2286 break;
2287 }
2288 return TRUE;
2289}
2290
2291void EditorToolBar::OnMouseEnter(int toolIndex)
2292{
2293 wxFrame *frame = (wxFrame *)GetParent();
2294
2295 if (!frame) return;
2296
2297 if (toolIndex > -1)
2298 {
2299 switch (toolIndex)
2300 {
2301 case TOOLBAR_LOAD_FILE:
2302 frame->SetStatusText("Load project file");
2303 break;
2304 case TOOLBAR_SAVE_FILE:
2305 frame->SetStatusText("Save project file");
2306 break;
2307 case TOOLBAR_NEW:
2308 frame->SetStatusText("Create a new resource");
2309 break;
2310 case TOOLBAR_FORMAT_HORIZ:
2311 frame->SetStatusText("Align items horizontally");
2312 break;
2313 case TOOLBAR_FORMAT_VERT:
2314 frame->SetStatusText("Align items vertically");
2315 break;
2316 case TOOLBAR_FORMAT_HORIZ_LEFT_ALIGN:
2317 frame->SetStatusText("Left-align items");
2318 break;
2319 case TOOLBAR_FORMAT_HORIZ_RIGHT_ALIGN:
2320 frame->SetStatusText("Right-align items");
2321 break;
2322 case TOOLBAR_FORMAT_VERT_TOP_ALIGN:
2323 frame->SetStatusText("Top-align items");
2324 break;
2325 case TOOLBAR_FORMAT_VERT_BOT_ALIGN:
2326 frame->SetStatusText("Bottom-align items");
2327 break;
2328 case TOOLBAR_COPY_SIZE:
2329 frame->SetStatusText("Copy size from first selection");
2330 break;
2331 case TOOLBAR_TO_FRONT:
2332 frame->SetStatusText("Put image to front");
2333 break;
2334 case TOOLBAR_TO_BACK:
2335 frame->SetStatusText("Put image to back");
2336 break;
2337 case TOOLBAR_HELP:
2338 frame->SetStatusText("Display help contents");
2339 break;
2340 default:
2341 break;
2342 }
2343 }
2344 else frame->SetStatusText("");
2345}
2346