]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: samples/docview/view.cpp | |
3 | // Purpose: View classes implementation | |
4 | // Author: Julian Smart | |
5 | // Modified by: Vadim Zeitlin: merge with the MDI version and general cleanup | |
6 | // Created: 04/01/98 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 1998 Julian Smart | |
9 | // (c) 2008 Vadim Zeitlin | |
10 | // Licence: wxWindows license | |
11 | ///////////////////////////////////////////////////////////////////////////// | |
12 | ||
13 | // For compilers that support precompilation, includes "wx/wx.h". | |
14 | #include "wx/wxprec.h" | |
15 | ||
16 | #ifdef __BORLANDC__ | |
17 | #pragma hdrstop | |
18 | #endif | |
19 | ||
20 | #ifndef WX_PRECOMP | |
21 | #include "wx/wx.h" | |
22 | #endif | |
23 | ||
24 | #if !wxUSE_DOC_VIEW_ARCHITECTURE | |
25 | #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h! | |
26 | #endif | |
27 | ||
28 | #include "docview.h" | |
29 | #include "doc.h" | |
30 | #include "view.h" | |
31 | ||
32 | // ---------------------------------------------------------------------------- | |
33 | // DrawingView implementation | |
34 | // ---------------------------------------------------------------------------- | |
35 | ||
36 | IMPLEMENT_DYNAMIC_CLASS(DrawingView, wxView) | |
37 | ||
38 | BEGIN_EVENT_TABLE(DrawingView, wxView) | |
39 | EVT_MENU(wxID_CUT, DrawingView::OnCut) | |
40 | END_EVENT_TABLE() | |
41 | ||
42 | // What to do when a view is created. Creates actual | |
43 | // windows for displaying the view. | |
44 | bool DrawingView::OnCreate(wxDocument *doc, long WXUNUSED(flags) ) | |
45 | { | |
46 | MyApp& app = wxGetApp(); | |
47 | if ( app.GetMode() != MyApp::Mode_Single ) | |
48 | { | |
49 | // create a new window and canvas inside it | |
50 | m_frame = app.CreateChildFrame(doc, this, true); | |
51 | m_frame->SetTitle("Drawing View"); | |
52 | ||
53 | m_canvas = new MyCanvas(this, m_frame); | |
54 | m_frame->Show(true); | |
55 | } | |
56 | else // single document mode | |
57 | { | |
58 | // reuse the existing window and canvas | |
59 | m_frame = wxStaticCast(app.GetTopWindow(), wxFrame); | |
60 | m_canvas = app.GetMainWindowCanvas(); | |
61 | m_canvas->SetView(this); | |
62 | ||
63 | // Associate the appropriate frame with this view. | |
64 | SetFrame(m_frame); | |
65 | ||
66 | // Make sure the document manager knows that this is the | |
67 | // current view. | |
68 | Activate(true); | |
69 | ||
70 | // Initialize the edit menu Undo and Redo items | |
71 | doc->GetCommandProcessor()->SetEditMenu(app.GetMainWindowEditMenu()); | |
72 | doc->GetCommandProcessor()->Initialize(); | |
73 | } | |
74 | ||
75 | return true; | |
76 | } | |
77 | ||
78 | // Sneakily gets used for default print/preview as well as drawing on the | |
79 | // screen. | |
80 | void DrawingView::OnDraw(wxDC *dc) | |
81 | { | |
82 | dc->SetPen(*wxBLACK_PEN); | |
83 | ||
84 | // simply draw all lines of all segments | |
85 | const DoodleSegments& segments = GetDocument()->GetSegments(); | |
86 | for ( DoodleSegments::const_iterator i = segments.begin(); | |
87 | i != segments.end(); | |
88 | ++i ) | |
89 | { | |
90 | const DoodleLines& lines = i->GetLines(); | |
91 | for ( DoodleLines::const_iterator j = lines.begin(); | |
92 | j != lines.end(); | |
93 | ++j ) | |
94 | { | |
95 | const DoodleLine& line = *j; | |
96 | ||
97 | dc->DrawLine(line.x1, line.y1, line.x2, line.y2); | |
98 | } | |
99 | } | |
100 | } | |
101 | ||
102 | DrawingDocument* DrawingView::GetDocument() | |
103 | { | |
104 | return wxStaticCast(wxView::GetDocument(), DrawingDocument); | |
105 | } | |
106 | ||
107 | void DrawingView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint)) | |
108 | { | |
109 | if ( m_canvas ) | |
110 | m_canvas->Refresh(); | |
111 | } | |
112 | ||
113 | // Clean up windows used for displaying the view. | |
114 | bool DrawingView::OnClose(bool deleteWindow) | |
115 | { | |
116 | if ( !GetDocument()->Close() ) | |
117 | return false; | |
118 | ||
119 | Activate(false); | |
120 | ||
121 | // Clear the canvas in single-window mode in which it stays alive | |
122 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) | |
123 | { | |
124 | m_canvas->ClearBackground(); | |
125 | m_canvas->ResetView(); | |
126 | m_canvas = NULL; | |
127 | ||
128 | if ( m_frame ) | |
129 | m_frame->SetTitle(wxTheApp->GetAppDisplayName()); | |
130 | } | |
131 | else // not single window mode | |
132 | { | |
133 | if ( deleteWindow ) | |
134 | wxDELETE(m_frame); | |
135 | } | |
136 | ||
137 | SetFrame(NULL); | |
138 | ||
139 | return true; | |
140 | } | |
141 | ||
142 | void DrawingView::OnCut(wxCommandEvent& WXUNUSED(event) ) | |
143 | { | |
144 | DrawingDocument * const doc = GetDocument(); | |
145 | ||
146 | doc->GetCommandProcessor()->Submit(new DrawingRemoveSegmentCommand(doc)); | |
147 | } | |
148 | ||
149 | // ---------------------------------------------------------------------------- | |
150 | // TextEditView implementation | |
151 | // ---------------------------------------------------------------------------- | |
152 | ||
153 | IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView) | |
154 | ||
155 | BEGIN_EVENT_TABLE(TextEditView, wxView) | |
156 | EVT_MENU(wxID_COPY, TextEditView::OnCopy) | |
157 | EVT_MENU(wxID_PASTE, TextEditView::OnPaste) | |
158 | EVT_MENU(wxID_SELECTALL, TextEditView::OnSelectAll) | |
159 | END_EVENT_TABLE() | |
160 | ||
161 | bool TextEditView::OnCreate(wxDocument *doc, long WXUNUSED(flags)) | |
162 | { | |
163 | m_frame = wxGetApp().CreateChildFrame(doc, this, false); | |
164 | m_text = new wxTextCtrl(m_frame, wxID_ANY, "", | |
165 | wxPoint(0, 0), m_frame->GetClientSize(), | |
166 | wxTE_MULTILINE); | |
167 | ||
168 | m_frame->SetTitle("Text View"); | |
169 | m_frame->Show(true); | |
170 | ||
171 | Activate(true); | |
172 | ||
173 | return true; | |
174 | } | |
175 | ||
176 | void TextEditView::OnDraw(wxDC *WXUNUSED(dc)) | |
177 | { | |
178 | // nothing to do here, wxTextCtrl draws itself | |
179 | } | |
180 | ||
181 | bool TextEditView::OnClose(bool deleteWindow) | |
182 | { | |
183 | if ( !GetDocument()->Close() ) | |
184 | return false; | |
185 | ||
186 | Activate(false); | |
187 | ||
188 | if ( wxGetApp().GetMode() == MyApp::Mode_Single ) | |
189 | { | |
190 | m_text->Clear(); | |
191 | } | |
192 | else // not single window mode | |
193 | { | |
194 | if ( deleteWindow ) | |
195 | wxDELETE(m_frame); | |
196 | } | |
197 | ||
198 | return true; | |
199 | } | |
200 | ||
201 | // ---------------------------------------------------------------------------- | |
202 | // MyCanvas implementation | |
203 | // ---------------------------------------------------------------------------- | |
204 | ||
205 | BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) | |
206 | EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent) | |
207 | END_EVENT_TABLE() | |
208 | ||
209 | // Define a constructor for my canvas | |
210 | MyCanvas::MyCanvas(wxView *view, wxWindow *parent) | |
211 | : wxScrolledWindow(parent, wxID_ANY, wxPoint(0, 0), parent->GetClientSize()) | |
212 | { | |
213 | m_view = view; | |
214 | m_currentSegment = NULL; | |
215 | m_lastMousePos = wxDefaultPosition; | |
216 | ||
217 | SetCursor(wxCursor(wxCURSOR_PENCIL)); | |
218 | ||
219 | // this is completely arbitrary and is done just for illustration purposes | |
220 | SetVirtualSize(1000, 1000); | |
221 | SetScrollRate(20, 20); | |
222 | ||
223 | SetBackgroundColour(*wxWHITE); | |
224 | } | |
225 | ||
226 | MyCanvas::~MyCanvas() | |
227 | { | |
228 | delete m_currentSegment; | |
229 | } | |
230 | ||
231 | // Define the repainting behaviour | |
232 | void MyCanvas::OnDraw(wxDC& dc) | |
233 | { | |
234 | if ( m_view ) | |
235 | m_view->OnDraw(& dc); | |
236 | } | |
237 | ||
238 | // This implements a tiny doodling program. Drag the mouse using the left | |
239 | // button. | |
240 | void MyCanvas::OnMouseEvent(wxMouseEvent& event) | |
241 | { | |
242 | if ( !m_view ) | |
243 | return; | |
244 | ||
245 | wxClientDC dc(this); | |
246 | PrepareDC(dc); | |
247 | ||
248 | dc.SetPen(*wxBLACK_PEN); | |
249 | ||
250 | const wxPoint pt(event.GetLogicalPosition(dc)); | |
251 | ||
252 | // is this the end of the current segment? | |
253 | if ( m_currentSegment && event.LeftUp() ) | |
254 | { | |
255 | if ( !m_currentSegment->IsEmpty() ) | |
256 | { | |
257 | // We've got a valid segment on mouse left up, so store it. | |
258 | DrawingDocument * const | |
259 | doc = wxStaticCast(m_view->GetDocument(), DrawingDocument); | |
260 | ||
261 | doc->GetCommandProcessor()->Submit( | |
262 | new DrawingAddSegmentCommand(doc, *m_currentSegment)); | |
263 | ||
264 | doc->Modify(true); | |
265 | } | |
266 | ||
267 | delete m_currentSegment; | |
268 | m_currentSegment = NULL; | |
269 | } | |
270 | ||
271 | // is this the start of a new segment? | |
272 | if ( m_lastMousePos != wxDefaultPosition && event.Dragging() ) | |
273 | { | |
274 | if ( !m_currentSegment ) | |
275 | m_currentSegment = new DoodleSegment; | |
276 | ||
277 | m_currentSegment->AddLine(m_lastMousePos, pt); | |
278 | ||
279 | dc.DrawLine(m_lastMousePos, pt); | |
280 | } | |
281 | ||
282 | m_lastMousePos = pt; | |
283 | } | |
284 |