]> git.saurik.com Git - wxWidgets.git/blame - samples/docview/view.cpp
Fix wxComboCtrlBase::DoGetSizeFromTextSize() performance regression.
[wxWidgets.git] / samples / docview / view.cpp
CommitLineData
457814b5 1/////////////////////////////////////////////////////////////////////////////
2d1df0fc
VZ
2// Name: samples/docview/view.cpp
3// Purpose: View classes implementation
457814b5 4// Author: Julian Smart
2d1df0fc 5// Modified by: Vadim Zeitlin: merge with the MDI version and general cleanup
457814b5 6// Created: 04/01/98
2d1df0fc
VZ
7// Copyright: (c) 1998 Julian Smart
8// (c) 2008 Vadim Zeitlin
526954c5 9// Licence: wxWindows licence
457814b5
JS
10/////////////////////////////////////////////////////////////////////////////
11
457814b5
JS
12// For compilers that support precompilation, includes "wx/wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
2d1df0fc 16 #pragma hdrstop
457814b5
JS
17#endif
18
19#ifndef WX_PRECOMP
2d1df0fc 20 #include "wx/wx.h"
457814b5
JS
21#endif
22
e4b19d9b 23#if !wxUSE_DOC_VIEW_ARCHITECTURE
2d1df0fc 24 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
457814b5
JS
25#endif
26
27#include "docview.h"
28#include "doc.h"
29#include "view.h"
30
2d1df0fc
VZ
31// ----------------------------------------------------------------------------
32// DrawingView implementation
33// ----------------------------------------------------------------------------
457814b5 34
2d1df0fc 35IMPLEMENT_DYNAMIC_CLASS(DrawingView, wxView)
457814b5
JS
36
37BEGIN_EVENT_TABLE(DrawingView, wxView)
2d1df0fc 38 EVT_MENU(wxID_CUT, DrawingView::OnCut)
457814b5
JS
39END_EVENT_TABLE()
40
41// What to do when a view is created. Creates actual
42// windows for displaying the view.
9b341e6f 43bool DrawingView::OnCreate(wxDocument *doc, long flags)
457814b5 44{
9b341e6f
VZ
45 if ( !wxView::OnCreate(doc, flags) )
46 return false;
47
2d1df0fc
VZ
48 MyApp& app = wxGetApp();
49 if ( app.GetMode() != MyApp::Mode_Single )
f6bcfd97 50 {
2d1df0fc 51 // create a new window and canvas inside it
9b341e6f
VZ
52 wxFrame* frame = app.CreateChildFrame(this, true);
53 wxASSERT(frame == GetFrame());
54 m_canvas = new MyCanvas(this);
c346d3d2 55 frame->Show();
f6bcfd97 56 }
2d1df0fc 57 else // single document mode
f6bcfd97 58 {
2d1df0fc 59 // reuse the existing window and canvas
2d1df0fc
VZ
60 m_canvas = app.GetMainWindowCanvas();
61 m_canvas->SetView(this);
6bdf5153 62
f6bcfd97 63 // Initialize the edit menu Undo and Redo items
2d1df0fc 64 doc->GetCommandProcessor()->SetEditMenu(app.GetMainWindowEditMenu());
f6bcfd97
BP
65 doc->GetCommandProcessor()->Initialize();
66 }
6bdf5153 67
f2aea0d1 68 return true;
457814b5
JS
69}
70
2d1df0fc
VZ
71// Sneakily gets used for default print/preview as well as drawing on the
72// screen.
457814b5
JS
73void DrawingView::OnDraw(wxDC *dc)
74{
f6bcfd97 75 dc->SetPen(*wxBLACK_PEN);
6bdf5153 76
2d1df0fc
VZ
77 // simply draw all lines of all segments
78 const DoodleSegments& segments = GetDocument()->GetSegments();
79 for ( DoodleSegments::const_iterator i = segments.begin();
80 i != segments.end();
81 ++i )
f6bcfd97 82 {
2d1df0fc 83 const DoodleLines& lines = i->GetLines();
ce00f59b 84 for ( DoodleLines::const_iterator j = lines.begin();
2d1df0fc
VZ
85 j != lines.end();
86 ++j )
87 {
88 const DoodleLine& line = *j;
89
90 dc->DrawLine(line.x1, line.y1, line.x2, line.y2);
91 }
f6bcfd97 92 }
457814b5
JS
93}
94
6bdf5153
VZ
95DrawingDocument* DrawingView::GetDocument()
96{
97 return wxStaticCast(wxView::GetDocument(), DrawingDocument);
98}
99
f37f49b6 100void DrawingView::OnUpdate(wxView* sender, wxObject* hint)
457814b5 101{
f37f49b6 102 wxView::OnUpdate(sender, hint);
2d1df0fc 103 if ( m_canvas )
6bdf5153 104 m_canvas->Refresh();
457814b5
JS
105}
106
107// Clean up windows used for displaying the view.
108bool DrawingView::OnClose(bool deleteWindow)
109{
ab5259d9 110 if ( !wxView::OnClose(deleteWindow) )
f2aea0d1 111 return false;
6bdf5153 112
f2aea0d1 113 Activate(false);
6bdf5153 114
2d1df0fc
VZ
115 // Clear the canvas in single-window mode in which it stays alive
116 if ( wxGetApp().GetMode() == MyApp::Mode_Single )
117 {
118 m_canvas->ClearBackground();
119 m_canvas->ResetView();
120 m_canvas = NULL;
121
9b341e6f
VZ
122 if (GetFrame())
123 wxStaticCast(GetFrame(), wxFrame)->SetTitle(wxTheApp->GetAppDisplayName());
2d1df0fc
VZ
124 }
125 else // not single window mode
f6bcfd97 126 {
2d1df0fc 127 if ( deleteWindow )
9b341e6f
VZ
128 {
129 GetFrame()->Destroy();
130 SetFrame(NULL);
131 }
f6bcfd97 132 }
f2aea0d1 133 return true;
457814b5
JS
134}
135
e3e65dac 136void DrawingView::OnCut(wxCommandEvent& WXUNUSED(event) )
457814b5 137{
2d1df0fc
VZ
138 DrawingDocument * const doc = GetDocument();
139
140 doc->GetCommandProcessor()->Submit(new DrawingRemoveSegmentCommand(doc));
457814b5
JS
141}
142
2d1df0fc
VZ
143// ----------------------------------------------------------------------------
144// TextEditView implementation
145// ----------------------------------------------------------------------------
146
457814b5
JS
147IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView)
148
4e553af1
VZ
149BEGIN_EVENT_TABLE(TextEditView, wxView)
150 EVT_MENU(wxID_COPY, TextEditView::OnCopy)
151 EVT_MENU(wxID_PASTE, TextEditView::OnPaste)
152 EVT_MENU(wxID_SELECTALL, TextEditView::OnSelectAll)
153END_EVENT_TABLE()
154
9b341e6f 155bool TextEditView::OnCreate(wxDocument *doc, long flags)
457814b5 156{
9b341e6f
VZ
157 if ( !wxView::OnCreate(doc, flags) )
158 return false;
2d1df0fc 159
9b341e6f
VZ
160 wxFrame* frame = wxGetApp().CreateChildFrame(this, false);
161 wxASSERT(frame == GetFrame());
162 m_text = new wxTextCtrl(frame, wxID_ANY, "",
163 wxDefaultPosition, wxDefaultSize,
164 wxTE_MULTILINE);
165 frame->Show();
6bdf5153 166
f2aea0d1 167 return true;
457814b5
JS
168}
169
2d1df0fc 170void TextEditView::OnDraw(wxDC *WXUNUSED(dc))
457814b5 171{
2d1df0fc 172 // nothing to do here, wxTextCtrl draws itself
457814b5
JS
173}
174
175bool TextEditView::OnClose(bool deleteWindow)
176{
ab5259d9 177 if ( !wxView::OnClose(deleteWindow) )
f2aea0d1 178 return false;
6bdf5153 179
f2aea0d1 180 Activate(false);
6bdf5153 181
2d1df0fc 182 if ( wxGetApp().GetMode() == MyApp::Mode_Single )
f6bcfd97 183 {
2d1df0fc 184 m_text->Clear();
f6bcfd97 185 }
2d1df0fc
VZ
186 else // not single window mode
187 {
188 if ( deleteWindow )
9b341e6f
VZ
189 {
190 GetFrame()->Destroy();
191 SetFrame(NULL);
192 }
2d1df0fc 193 }
f2aea0d1 194 return true;
457814b5
JS
195}
196
2d1df0fc
VZ
197// ----------------------------------------------------------------------------
198// MyCanvas implementation
199// ----------------------------------------------------------------------------
457814b5
JS
200
201BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
202 EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
203END_EVENT_TABLE()
204
205// Define a constructor for my canvas
2d1df0fc 206MyCanvas::MyCanvas(wxView *view, wxWindow *parent)
9b341e6f 207 : wxScrolledWindow(parent ? parent : view->GetFrame())
457814b5 208{
6bdf5153 209 m_view = view;
2d1df0fc
VZ
210 m_currentSegment = NULL;
211 m_lastMousePos = wxDefaultPosition;
212
213 SetCursor(wxCursor(wxCURSOR_PENCIL));
214
215 // this is completely arbitrary and is done just for illustration purposes
216 SetVirtualSize(1000, 1000);
217 SetScrollRate(20, 20);
218
219 SetBackgroundColour(*wxWHITE);
220}
221
222MyCanvas::~MyCanvas()
223{
224 delete m_currentSegment;
457814b5
JS
225}
226
227// Define the repainting behaviour
228void MyCanvas::OnDraw(wxDC& dc)
229{
2d1df0fc 230 if ( m_view )
6bdf5153 231 m_view->OnDraw(& dc);
457814b5
JS
232}
233
2d1df0fc
VZ
234// This implements a tiny doodling program. Drag the mouse using the left
235// button.
457814b5
JS
236void MyCanvas::OnMouseEvent(wxMouseEvent& event)
237{
2d1df0fc 238 if ( !m_view )
f6bcfd97 239 return;
6bdf5153 240
f6bcfd97
BP
241 wxClientDC dc(this);
242 PrepareDC(dc);
6bdf5153 243
f6bcfd97 244 dc.SetPen(*wxBLACK_PEN);
6bdf5153 245
2d1df0fc 246 const wxPoint pt(event.GetLogicalPosition(dc));
6bdf5153 247
2d1df0fc
VZ
248 // is this the end of the current segment?
249 if ( m_currentSegment && event.LeftUp() )
457814b5 250 {
2d1df0fc 251 if ( !m_currentSegment->IsEmpty() )
f6bcfd97
BP
252 {
253 // We've got a valid segment on mouse left up, so store it.
2d1df0fc
VZ
254 DrawingDocument * const
255 doc = wxStaticCast(m_view->GetDocument(), DrawingDocument);
6bdf5153 256
2d1df0fc
VZ
257 doc->GetCommandProcessor()->Submit(
258 new DrawingAddSegmentCommand(doc, *m_currentSegment));
6bdf5153 259
2d1df0fc 260 doc->Modify(true);
f6bcfd97 261 }
2d1df0fc 262
5276b0a5 263 wxDELETE(m_currentSegment);
457814b5 264 }
6bdf5153 265
2d1df0fc
VZ
266 // is this the start of a new segment?
267 if ( m_lastMousePos != wxDefaultPosition && event.Dragging() )
457814b5 268 {
2d1df0fc
VZ
269 if ( !m_currentSegment )
270 m_currentSegment = new DoodleSegment;
6bdf5153 271
2d1df0fc 272 m_currentSegment->AddLine(m_lastMousePos, pt);
6bdf5153 273
2d1df0fc 274 dc.DrawLine(m_lastMousePos, pt);
457814b5 275 }
457814b5 276
2d1df0fc 277 m_lastMousePos = pt;
457814b5
JS
278}
279
f37f49b6 280// ----------------------------------------------------------------------------
2d4a03f8 281// ImageCanvas implementation
f37f49b6
JS
282// ----------------------------------------------------------------------------
283
f37f49b6 284// Define a constructor for my canvas
9b341e6f
VZ
285ImageCanvas::ImageCanvas(wxView* view)
286 : wxScrolledWindow(view->GetFrame())
f37f49b6
JS
287{
288 m_view = view;
9b341e6f 289 SetScrollRate( 10, 10 );
f37f49b6
JS
290}
291
292// Define the repainting behaviour
2d4a03f8 293void ImageCanvas::OnDraw(wxDC& dc)
f37f49b6
JS
294{
295 if ( m_view )
296 m_view->OnDraw(& dc);
297}
298
299// ----------------------------------------------------------------------------
2d4a03f8 300// ImageView implementation
f37f49b6
JS
301// ----------------------------------------------------------------------------
302
2d4a03f8 303IMPLEMENT_DYNAMIC_CLASS(ImageView, wxView)
f37f49b6 304
2d4a03f8 305ImageDocument* ImageView::GetDocument()
f37f49b6 306{
2d4a03f8 307 return wxStaticCast(wxView::GetDocument(), ImageDocument);
f37f49b6
JS
308}
309
9b341e6f 310bool ImageView::OnCreate(wxDocument* doc, long flags)
f37f49b6 311{
9b341e6f
VZ
312 if ( !wxView::OnCreate(doc, flags) )
313 return false;
314
315 wxFrame* frame = wxGetApp().CreateChildFrame(this, false);
316 wxASSERT(frame == GetFrame());
317 m_canvas = new ImageCanvas(this);
318 frame->Show();
319
f37f49b6
JS
320 return true;
321}
322
2d4a03f8 323void ImageView::OnUpdate(wxView* sender, wxObject* hint)
f37f49b6
JS
324{
325 wxView::OnUpdate(sender, hint);
2d4a03f8
VZ
326 wxImage image = GetDocument()->GetImage();
327 if ( image.IsOk() )
f37f49b6 328 {
2d4a03f8 329 m_canvas->SetVirtualSize(image.GetWidth(), image.GetHeight());
f37f49b6
JS
330 }
331}
332
2d4a03f8 333void ImageView::OnDraw(wxDC* dc)
f37f49b6 334{
2d4a03f8
VZ
335 wxImage image = GetDocument()->GetImage();
336 if ( image.IsOk() )
f37f49b6 337 {
11c278c4 338 dc->DrawBitmap(wxBitmap(image), 0, 0, true /* use mask */);
f37f49b6
JS
339 }
340}
341
2d4a03f8 342bool ImageView::OnClose(bool deleteWindow)
f37f49b6 343{
ab5259d9 344 if ( !wxView::OnClose(deleteWindow) )
f37f49b6
JS
345 return false;
346
347 Activate(false);
348
349 if ( wxGetApp().GetMode() == MyApp::Mode_Single )
350 {
351 GetDocument()->DeleteContents();
352 }
353 else // not single window mode
354 {
355 if ( deleteWindow )
9b341e6f
VZ
356 {
357 GetFrame()->Destroy();
358 SetFrame(NULL);
359 }
f37f49b6
JS
360 }
361 return true;
362}
363
4db97e24
VZ
364// ----------------------------------------------------------------------------
365// ImageDetailsView
366// ----------------------------------------------------------------------------
367
368ImageDetailsView::ImageDetailsView(ImageDetailsDocument *doc)
369 : wxView()
370{
371 SetDocument(doc);
372
373 m_frame = wxGetApp().CreateChildFrame(this, false);
374 m_frame->SetTitle("Image Details");
375
376 wxPanel * const panel = new wxPanel(m_frame);
377 wxFlexGridSizer * const sizer = new wxFlexGridSizer(2, wxSize(5, 5));
378 const wxSizerFlags
379 flags = wxSizerFlags().Align(wxALIGN_CENTRE_VERTICAL).Border();
380
381 sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &file:"), flags);
382 sizer->Add(new wxStaticText(panel, wxID_ANY, doc->GetFilename()), flags);
383
384 sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &type:"), flags);
385 wxString typeStr;
386 switch ( doc->GetType() )
387 {
388 case wxBITMAP_TYPE_PNG:
389 typeStr = "PNG";
390 break;
391
392 case wxBITMAP_TYPE_JPEG:
393 typeStr = "JPEG";
394 break;
395
396 default:
397 typeStr = "Unknown";
398 }
399 sizer->Add(new wxStaticText(panel, wxID_ANY, typeStr), flags);
400
401 sizer->Add(new wxStaticText(panel, wxID_ANY, "Image &size:"), flags);
402 wxSize size = doc->GetSize();
403 sizer->Add(new wxStaticText(panel, wxID_ANY,
404 wxString::Format("%d*%d", size.x, size.y)),
405 flags);
406
407 sizer->Add(new wxStaticText(panel, wxID_ANY, "Number of unique &colours:"),
408 flags);
409 sizer->Add(new wxStaticText(panel, wxID_ANY,
410 wxString::Format("%lu", doc->GetNumColours())),
411 flags);
412
413 sizer->Add(new wxStaticText(panel, wxID_ANY, "Uses &alpha:"), flags);
414 sizer->Add(new wxStaticText(panel, wxID_ANY,
415 doc->HasAlpha() ? "Yes" : "No"), flags);
416
417 panel->SetSizer(sizer);
418 m_frame->SetClientSize(panel->GetBestSize());
419 m_frame->Show(true);
420}
421
422void ImageDetailsView::OnDraw(wxDC * WXUNUSED(dc))
423{
424 // nothing to do here, we use controls to show our information
425}
426
427bool ImageDetailsView::OnClose(bool deleteWindow)
428{
429 if ( wxGetApp().GetMode() != MyApp::Mode_Single && deleteWindow )
430 {
431 delete m_frame;
432 m_frame = NULL;
433 }
434
435 return true;
436}