1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
5 // Modified by: 2008-10-31 Vadim Zeitlin: big clean up
8 // Copyright: (c) 1997 Julian Smart
9 // (c) 2008 Vadim Zeitlin
10 // Licence: wxWindows license
11 /////////////////////////////////////////////////////////////////////////////
13 // ===========================================================================
15 // ===========================================================================
17 // ---------------------------------------------------------------------------
19 // ---------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx/wx.h".
22 #include "wx/wxprec.h"
33 #include "wx/toolbar.h"
35 #if !defined(__WXMSW__)
36 #include "../sample.xpm"
40 #include "bitmaps/new.xpm"
41 #include "bitmaps/open.xpm"
42 #include "bitmaps/save.xpm"
43 #include "bitmaps/copy.xpm"
44 #include "bitmaps/cut.xpm"
45 #include "bitmaps/paste.xpm"
46 #include "bitmaps/print.xpm"
47 #include "bitmaps/help.xpm"
49 // replace this 0 with 1 to build the sample using the generic MDI classes (you
50 // may also need to add src/generic/mdig.cpp to the build)
52 #include "wx/generic/mdig.h"
53 #define wxMDIParentFrame wxGenericMDIParentFrame
54 #define wxMDIChildFrame wxGenericMDIChildFrame
55 #define wxMDIClientWindow wxGenericMDIClientWindow
62 // ---------------------------------------------------------------------------
64 // ---------------------------------------------------------------------------
66 BEGIN_EVENT_TABLE(MyFrame
, wxMDIParentFrame
)
67 EVT_MENU(wxID_ABOUT
, MyFrame::OnAbout
)
68 EVT_MENU(wxID_NEW
, MyFrame::OnNewWindow
)
69 EVT_MENU(MDI_FULLSCREEN
, MyFrame::OnFullScreen
)
70 EVT_MENU(wxID_EXIT
, MyFrame::OnQuit
)
72 EVT_CLOSE(MyFrame::OnClose
)
75 // Note that wxID_NEW and wxID_ABOUT commands get passed
76 // to the parent window for processing, so no need to
77 // duplicate event handlers here.
78 BEGIN_EVENT_TABLE(MyChild
, wxMDIChildFrame
)
79 EVT_MENU(wxID_CLOSE
, MyChild::OnClose
)
80 EVT_MENU(MDI_REFRESH
, MyChild::OnRefresh
)
81 EVT_MENU(MDI_CHANGE_TITLE
, MyChild::OnChangeTitle
)
82 EVT_MENU(MDI_CHANGE_POSITION
, MyChild::OnChangePosition
)
83 EVT_MENU(MDI_CHANGE_SIZE
, MyChild::OnChangeSize
)
86 EVT_MENU(wxID_PASTE
, MyChild::OnPaste
)
87 EVT_UPDATE_UI(wxID_PASTE
, MyChild::OnUpdatePaste
)
88 #endif // wxUSE_CLIPBOARD
90 EVT_SIZE(MyChild::OnSize
)
91 EVT_MOVE(MyChild::OnMove
)
93 EVT_CLOSE(MyChild::OnCloseWindow
)
96 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
97 EVT_MOUSE_EVENTS(MyCanvas::OnEvent
)
100 // ===========================================================================
102 // ===========================================================================
104 // ---------------------------------------------------------------------------
106 // ---------------------------------------------------------------------------
108 // Initialise this in OnInit, not statically
111 if ( !wxApp::OnInit() )
114 // Create the main frame window
116 MyFrame
*frame
= new MyFrame
;
123 // ---------------------------------------------------------------------------
125 // ---------------------------------------------------------------------------
127 // Define my frame constructor
129 : wxMDIParentFrame(NULL
, wxID_ANY
, "wxWidgets MDI Sample",
130 wxDefaultPosition
, wxSize(500, 400))
132 SetIcon(wxICON(sample
));
136 wxMenu
*file_menu
= new wxMenu
;
138 file_menu
->Append(wxID_NEW
, "&New window\tCtrl-N", "Create a new child window");
139 file_menu
->AppendCheckItem(MDI_FULLSCREEN
, "Show &fullscreen\tCtrl-F");
140 file_menu
->Append(wxID_EXIT
, "&Exit\tAlt-X", "Quit the program");
142 wxMenu
*help_menu
= new wxMenu
;
143 help_menu
->Append(wxID_ABOUT
, "&About\tF1");
145 wxMenuBar
*menu_bar
= new wxMenuBar
;
147 menu_bar
->Append(file_menu
, "&File");
148 menu_bar
->Append(help_menu
, "&Help");
150 // Associate the menu bar with the frame
151 SetMenuBar(menu_bar
);
154 // Experimental: change the window menu
155 wxMenu
* windowMenu
= new wxMenu
;
156 windowMenu
->Append(5000, "My menu item!");
157 frame
->SetWindowMenu(windowMenu
);
159 #endif // wxUSE_MENUS
163 #endif // wxUSE_STATUSBAR
166 m_textWindow
= new wxTextCtrl(this, wxID_ANY
, "A help window",
167 wxDefaultPosition
, wxDefaultSize
,
168 wxTE_MULTILINE
| wxSUNKEN_BORDER
);
171 CreateToolBar(wxNO_BORDER
| wxTB_FLAT
| wxTB_HORIZONTAL
);
172 InitToolBar(GetToolBar());
173 #endif // wxUSE_TOOLBAR
177 wxAcceleratorEntry entries
[3];
178 entries
[0].Set(wxACCEL_CTRL
, (int) 'N', wxID_NEW
);
179 entries
[1].Set(wxACCEL_CTRL
, (int) 'X', wxID_EXIT
);
180 entries
[2].Set(wxACCEL_CTRL
, (int) 'A', wxID_ABOUT
);
181 wxAcceleratorTable
accel(3, entries
);
182 SetAcceleratorTable(accel
);
183 #endif // wxUSE_ACCEL
185 // connect it only now, after creating m_textWindow
186 Connect(wxEVT_SIZE
, wxSizeEventHandler(MyFrame::OnSize
));
191 // and disconnect it to prevent accessing already deleted m_textWindow in
192 // the size event handler if it's called during destruction
193 Disconnect(wxEVT_SIZE
, wxSizeEventHandler(MyFrame::OnSize
));
196 void MyFrame::OnClose(wxCloseEvent
& event
)
198 unsigned numChildren
= MyChild::GetChildrenCount();
199 if ( event
.CanVeto() && (numChildren
> 0) )
202 msg
.Printf("%d windows still open, close anyhow?", numChildren
);
203 if ( wxMessageBox(msg
, "Please confirm",
204 wxICON_QUESTION
| wxYES_NO
) != wxYES
)
215 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
220 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
) )
222 (void)wxMessageBox("wxWidgets 2.0 MDI Demo\n"
223 "Author: Julian Smart (c) 1997\n"
224 "Usage: mdi.exe", "About MDI Demo");
227 void MyFrame::OnNewWindow(wxCommandEvent
& WXUNUSED(event
) )
229 // create and show another child frame
230 MyChild
*subframe
= new MyChild(this);
231 subframe
->Show(true);
234 void MyFrame::OnFullScreen(wxCommandEvent
& event
)
236 ShowFullScreen(event
.IsChecked());
239 void MyFrame::OnSize(wxSizeEvent
& event
)
242 GetClientSize(&w
, &h
);
244 m_textWindow
->SetSize(0, 0, 200, h
);
245 GetClientWindow()->SetSize(200, 0, w
- 200, h
);
247 // FIXME: On wxX11, we need the MDI frame to process this
248 // event, but on other platforms this should not
250 #ifdef __WXUNIVERSAL__
258 void MyFrame::InitToolBar(wxToolBar
* toolBar
)
262 bitmaps
[0] = wxBitmap( new_xpm
);
263 bitmaps
[1] = wxBitmap( open_xpm
);
264 bitmaps
[2] = wxBitmap( save_xpm
);
265 bitmaps
[3] = wxBitmap( copy_xpm
);
266 bitmaps
[4] = wxBitmap( cut_xpm
);
267 bitmaps
[5] = wxBitmap( paste_xpm
);
268 bitmaps
[6] = wxBitmap( print_xpm
);
269 bitmaps
[7] = wxBitmap( help_xpm
);
271 toolBar
->AddTool(wxID_NEW
, "New", bitmaps
[0], "New file");
272 toolBar
->AddTool(1, "Open", bitmaps
[1], "Open file");
273 toolBar
->AddTool(2, "Save", bitmaps
[2], "Save file");
274 toolBar
->AddSeparator();
275 toolBar
->AddTool(3, "Copy", bitmaps
[3], "Copy");
276 toolBar
->AddTool(4, "Cut", bitmaps
[4], "Cut");
277 toolBar
->AddTool(5, "Paste", bitmaps
[5], "Paste");
278 toolBar
->AddSeparator();
279 toolBar
->AddTool(6, "Print", bitmaps
[6], "Print");
280 toolBar
->AddSeparator();
281 toolBar
->AddTool(wxID_ABOUT
, "About", bitmaps
[7], "Help");
285 #endif // wxUSE_TOOLBAR
287 // ---------------------------------------------------------------------------
289 // ---------------------------------------------------------------------------
291 // Define a constructor for my canvas
292 MyCanvas::MyCanvas(wxWindow
*parent
, const wxPoint
& pos
, const wxSize
& size
)
293 : wxScrolledWindow(parent
, wxID_ANY
, pos
, size
,
295 wxNO_FULL_REPAINT_ON_RESIZE
|
296 wxVSCROLL
| wxHSCROLL
)
298 SetBackgroundColour(wxColour("WHITE"));
299 SetCursor(wxCursor(wxCURSOR_PENCIL
));
301 SetScrollbars(20, 20, 50, 50);
306 // Define the repainting behaviour
307 void MyCanvas::OnDraw(wxDC
& dc
)
309 if ( !m_text
.empty() )
310 dc
.DrawText(m_text
, 10, 10);
312 dc
.SetFont(*wxSWISS_FONT
);
313 dc
.SetPen(*wxGREEN_PEN
);
314 dc
.DrawLine(0, 0, 200, 200);
315 dc
.DrawLine(200, 0, 0, 200);
317 dc
.SetBrush(*wxCYAN_BRUSH
);
318 dc
.SetPen(*wxRED_PEN
);
319 dc
.DrawRectangle(100, 100, 100, 50);
320 dc
.DrawRoundedRectangle(150, 150, 100, 50, 20);
322 dc
.DrawEllipse(250, 250, 100, 50);
324 dc
.DrawSpline(50, 200, 50, 100, 200, 10);
325 #endif // wxUSE_SPLINES
326 dc
.DrawLine(50, 230, 200, 230);
327 dc
.DrawText("This is a test string", 50, 230);
330 points
[0].x
= 200; points
[0].y
= 300;
331 points
[1].x
= 100; points
[1].y
= 400;
332 points
[2].x
= 300; points
[2].y
= 400;
334 dc
.DrawPolygon(3, points
);
337 // This implements a tiny doodling program! Drag the mouse using the left
339 void MyCanvas::OnEvent(wxMouseEvent
& event
)
344 wxPoint
pt(event
.GetLogicalPosition(dc
));
346 static long xpos
= -1;
347 static long ypos
= -1;
349 if (xpos
> -1 && ypos
> -1 && event
.Dragging())
351 dc
.SetPen(*wxBLACK_PEN
);
352 dc
.DrawLine(xpos
, ypos
, pt
.x
, pt
.y
);
361 // ---------------------------------------------------------------------------
363 // ---------------------------------------------------------------------------
365 unsigned MyChild::ms_numChildren
= 0;
367 MyChild::MyChild(wxMDIParentFrame
*parent
)
372 wxString::Format("Child %u", ++ms_numChildren
)
375 m_canvas
= new MyCanvas(this, wxPoint(0, 0), GetClientSize());
377 SetIcon(wxICON(chart
));
379 const bool canBeResized
= !IsAlwaysMaximized();
381 // create our menubar: it will be shown instead of the main frame one when
385 wxMenu
*file_menu
= new wxMenu
;
387 file_menu
->Append(wxID_NEW
, "&New window\tCtrl-N");
388 file_menu
->Append(wxID_CLOSE
, "&Close child\tCtrl-W", "Close this window");
389 file_menu
->AppendCheckItem(MDI_FULLSCREEN
, "Show &fullscreen\tCtrl-F");
390 file_menu
->Append(wxID_EXIT
, "&Exit\tAlt-X", "Quit the program");
392 wxMenu
*option_menu
= new wxMenu
;
394 option_menu
->Append(MDI_REFRESH
, "&Refresh picture");
395 option_menu
->Append(MDI_CHANGE_TITLE
, "Change &title...\tCtrl-T");
398 option_menu
->AppendSeparator();
399 option_menu
->Append(MDI_CHANGE_POSITION
, "Move frame\tCtrl-M");
400 option_menu
->Append(MDI_CHANGE_SIZE
, "Resize frame\tCtrl-S");
403 option_menu
->AppendSeparator();
404 option_menu
->Append(wxID_PASTE
, "Copy text from clipboard\tCtrl-V");
405 #endif // wxUSE_CLIPBOARD
407 wxMenu
*help_menu
= new wxMenu
;
408 help_menu
->Append(wxID_ABOUT
, "&About");
410 wxMenuBar
*menu_bar
= new wxMenuBar
;
412 menu_bar
->Append(file_menu
, "&File");
413 menu_bar
->Append(option_menu
, "&Child");
414 menu_bar
->Append(help_menu
, "&Help");
416 // Associate the menu bar with the frame
417 SetMenuBar(menu_bar
);
418 #endif // wxUSE_MENUS
420 // this should work for MDI frames as well as for normal ones, provided
421 // they can be resized at all
423 SetSizeHints(100, 100);
431 void MyChild::OnClose(wxCommandEvent
& WXUNUSED(event
))
436 void MyChild::OnRefresh(wxCommandEvent
& WXUNUSED(event
))
442 void MyChild::OnChangePosition(wxCommandEvent
& WXUNUSED(event
))
447 void MyChild::OnChangeSize(wxCommandEvent
& WXUNUSED(event
))
449 SetClientSize(100, 100);
452 void MyChild::OnChangeTitle(wxCommandEvent
& WXUNUSED(event
))
455 static wxString s_title
= "Canvas Frame";
457 wxString title
= wxGetTextFromUser("Enter the new title for MDI child",
458 "MDI sample question",
460 GetParent()->GetParent());
466 #endif // wxUSE_TEXTDLG
469 void MyChild::OnActivate(wxActivateEvent
& event
)
471 if ( event
.GetActive() && m_canvas
)
472 m_canvas
->SetFocus();
475 void MyChild::OnMove(wxMoveEvent
& event
)
477 // VZ: here everything is totally wrong under MSW, the positions are
478 // different and both wrong (pos2 is off by 2 pixels for me which seems
479 // to be the width of the MDI canvas border)
480 wxPoint pos1
= event
.GetPosition(),
481 pos2
= GetPosition();
482 wxLogStatus("position from event: (%d, %d), from frame (%d, %d)",
483 pos1
.x
, pos1
.y
, pos2
.x
, pos2
.y
);
488 void MyChild::OnSize(wxSizeEvent
& event
)
490 // VZ: under MSW the size event carries the client size (quite
491 // unexpectedly) *except* for the very first one which has the full
492 // size... what should it really be? TODO: check under wxGTK
493 wxSize size1
= event
.GetSize(),
495 size3
= GetClientSize();
496 wxLogStatus("size from event: %dx%d, from frame %dx%d, client %dx%d",
497 size1
.x
, size1
.y
, size2
.x
, size2
.y
, size3
.x
, size3
.y
);
502 void MyChild::OnCloseWindow(wxCloseEvent
& event
)
504 if ( m_canvas
&& m_canvas
->IsDirty() )
506 if ( wxMessageBox("Really close?", "Please confirm",
507 wxICON_QUESTION
| wxYES_NO
) != wxYES
)
520 #include "wx/clipbrd.h"
522 void MyChild::OnPaste(wxCommandEvent
& WXUNUSED(event
))
524 wxClipboardLocker lock
;
525 wxTextDataObject data
;
526 m_canvas
->SetText(wxTheClipboard
->GetData(data
)
528 : wxString("No text on clipboard"));
531 void MyChild::OnUpdatePaste(wxUpdateUIEvent
& event
)
533 wxClipboardLocker lock
;
534 event
.Enable( wxTheClipboard
->IsSupported(wxDF_TEXT
) );
537 #endif // wxUSE_CLIPBOARD