]> git.saurik.com Git - wxWidgets.git/blob - user/wxLayout/wxlwindow.cpp
60a8c8b7894b8c03d4f7e34c2621c711c7d54500
[wxWidgets.git] / user / wxLayout / wxlwindow.cpp
1 /*-*- c++ -*-********************************************************
2 * wxLwindow.h : a scrolled Window for displaying/entering rich text*
3 * *
4 * (C) 1998 by Karsten Ballüder (Ballueder@usa.net) *
5 * *
6 * $Id$
7 *******************************************************************/
8
9 #ifdef __GNUG__
10 # pragma implementation "wxlwindow.h"
11 #endif
12
13 //#include "Mpch.h"
14
15 #ifdef M_BASEDIR
16 # ifndef USE_PCH
17 # include "Mcommon.h"
18 # include "gui/wxMenuDefs.h"
19 # endif // USE_PCH
20 # include "gui/wxlwindow.h"
21 #else
22 # ifdef __WXMSW__
23 # include <windows.h>
24
25 # undef FindWindow
26 # undef GetCharWidth
27 # undef StartDoc
28 # endif
29
30 # include "wxlwindow.h"
31 # define TRACEMESSAGE(x)
32 #endif
33 # define WXL_VAR(x) cerr << #x " = " << x ;
34
35 BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
36 EVT_PAINT (wxLayoutWindow::OnPaint)
37 EVT_CHAR (wxLayoutWindow::OnChar)
38
39 EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseClick)
40 EVT_RIGHT_DOWN(wxLayoutWindow::OnRightMouseClick)
41 EVT_LEFT_DCLICK(wxLayoutWindow::OnMouseDblClick)
42 EVT_MENU(WXLOWIN_MENU_LARGER, wxLayoutWindow::OnMenu)
43 EVT_MENU(WXLOWIN_MENU_SMALLER, wxLayoutWindow::OnMenu)
44 EVT_MENU(WXLOWIN_MENU_UNDERLINE, wxLayoutWindow::OnMenu)
45 EVT_MENU(WXLOWIN_MENU_BOLD, wxLayoutWindow::OnMenu)
46 EVT_MENU(WXLOWIN_MENU_ITALICS, wxLayoutWindow::OnMenu)
47 EVT_MENU(WXLOWIN_MENU_ROMAN, wxLayoutWindow::OnMenu)
48 EVT_MENU(WXLOWIN_MENU_TYPEWRITER, wxLayoutWindow::OnMenu)
49 EVT_MENU(WXLOWIN_MENU_SANSSERIF, wxLayoutWindow::OnMenu)
50 END_EVENT_TABLE()
51
52 wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
53 : wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
54 wxHSCROLL | wxVSCROLL | wxBORDER)
55
56 {
57 m_ScrollbarsSet = false;
58 m_doSendEvents = false;
59 m_ViewStartX = 0; m_ViewStartY = 0;
60 m_DoPopupMenu = true;
61 m_PopupMenu = NULL;
62
63 CoordType
64 max_x, max_y, lineHeight;
65 m_llist.GetSize(&max_x, &max_y, &lineHeight);
66 SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1);
67 EnableScrolling(true,true);
68 }
69
70 #ifdef __WXMSW__
71 long
72 wxLayoutWindow::MSWGetDlgCode()
73 {
74 // if we don't return this, we won't get OnChar() events
75 return DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_WANTMESSAGE;
76 }
77 #endif //MSW
78
79 void
80 wxLayoutWindow::Update(void)
81 {
82 wxClientDC dc(this);
83 PrepareDC(dc);
84 if(IsDirty())
85 {
86 DoPaint(dc);
87 UpdateScrollbars();
88 ResetDirty();
89 }
90 m_llist.DrawCursor(dc);
91 }
92
93 void
94 wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
95 {
96 if(!m_doSendEvents) // nothing to do
97 return;
98
99 wxPaintDC dc( this );
100 PrepareDC( dc );
101 SetFocus();
102
103 wxPoint findPos;
104 findPos.x = dc.DeviceToLogicalX(event.GetX());
105 findPos.y = dc.DeviceToLogicalY(event.GetY());
106
107 TRACEMESSAGE(("wxLayoutWindow::OnMouse: (%d, %d) -> (%d, %d)",
108 event.GetX(), event.GetY(), findPos.x, findPos.y));
109
110 if(eventId == WXLOWIN_MENU_RCLICK && m_DoPopupMenu && m_llist.IsEditable())
111 {
112 // when does this menu get freed?
113 // how do we handle toggling? FIXME
114 PopupMenu(MakeFormatMenu(), event.GetX(), event.GetY());
115 return;
116 }
117 // find the object at this position
118 wxLayoutObjectBase *obj = m_llist.Find(findPos);
119 if(obj)
120 {
121 wxCommandEvent commandEvent(wxEVENT_TYPE_MENU_COMMAND, eventId);
122 commandEvent.SetEventObject( this );
123 commandEvent.SetClientData((char *)obj);
124 GetEventHandler()->ProcessEvent(commandEvent);
125 }
126 }
127
128 /*
129 * some simple keyboard handling
130 */
131 void
132 wxLayoutWindow::OnChar(wxKeyEvent& event)
133 {
134 if(! m_llist.IsEditable()) // do nothing
135 {
136 event.Skip();
137 return;
138 }
139
140 long keyCode = event.KeyCode();
141 wxPoint p;
142 CoordType help;
143
144 switch(event.KeyCode())
145 {
146 case WXK_RIGHT:
147 m_llist.MoveCursor(1);
148 break;
149 case WXK_LEFT:
150 m_llist.MoveCursor(-1);
151 break;
152 case WXK_UP:
153 m_llist.MoveCursor(0,-1);
154 break;
155 case WXK_DOWN:
156 m_llist.MoveCursor(0,1);
157 break;
158 case WXK_PRIOR:
159 m_llist.MoveCursor(0,-20);
160 break;
161 case WXK_NEXT:
162 m_llist.MoveCursor(0,20);
163 break;
164 case WXK_HOME:
165 p = m_llist.GetCursor();
166 p.x = 0;
167 m_llist.SetCursor(p);
168 break;
169 case WXK_END:
170 p = m_llist.GetCursor();
171 p.x = m_llist.GetLineLength(m_llist.GetCurrentObject());
172 m_llist.SetCursor(p);
173 break;
174 case WXK_DELETE :
175 if(event.ControlDown()) // delete to end of line
176 {
177 help = m_llist.GetLineLength(
178 m_llist.GetCurrentObject())
179 - m_llist.GetCursor().x;
180 m_llist.Delete(help ? help : 1);
181 }
182 else
183 m_llist.Delete(1);
184 break;
185 case WXK_BACK: // backspace
186 if(m_llist.MoveCursor(-1)) {
187 m_llist.Delete(1);
188 }
189 break;
190 case WXK_RETURN:
191 m_llist.LineBreak();
192 break;
193
194 #ifdef WXLAYOUT_DEBUG
195 case WXK_F1:
196 m_llist.Debug();
197 break;
198 case WXK_F2:
199 m_llist.WrapLine();
200 break;
201 #endif
202
203 default:
204 if(keyCode < 256 && keyCode >= 32)
205 {
206 String tmp;
207 tmp += keyCode;
208 m_llist.Insert(tmp);
209 m_llist.WrapLine();
210 }
211 break;
212 }
213
214 /** Scroll so that cursor is visible! */
215 int x0,y0,x1,y1,ux,uy;
216 ViewStart(&x0,&y0);
217 GetScrollPixelsPerUnit(&ux,&uy);
218 x0*=ux; y0*=uy;
219 GetClientSize(&x1,&y1);
220
221 wxPoint cc = m_llist.GetCursorCoords();
222 int nx = x0, ny = y0;
223 // when within 10% of borders, scroll to center
224 if(cc.y > y0+(9*y1)/10)
225 ny = cc.y - y1/5;
226 else if (cc.y < y0+y1/10)
227 {
228 ny = cc.y-y1/2;
229 if(ny < 0) ny = 0;
230 }
231 if(cc.x > x0+(9*x1)/10)
232 nx = cc.x - x1/5;
233 else if (cc.x < x0+x1/10)
234 {
235 nx = cc.x-x1/2;
236 if(nx < 0) nx = 0;
237 }
238 Scroll(nx,ny);
239
240 Update();
241 }
242
243 void
244 wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
245 {
246 wxPaintDC dc( this );
247 PrepareDC( dc );
248
249 DoPaint(dc);
250
251 // wxGTK: wxMemoryDC broken?
252 #if 0
253 int x0,y0,x1,y1;
254 ViewStart(&x0,&y0);
255 GetSize(&x1,&y1);
256 WXL_VAR(x0); WXL_VAR(y0);
257 WXL_VAR(x1); WXL_VAR(y1);
258
259 wxMemoryDC(memdc);
260 wxBitmap bm(x1,y1);
261 memdc.SelectObject(bm);
262
263 // make temporary copy and edit this
264 memdc.SetDeviceOrigin(x0,y0);
265 memdc.Blit(x0,y0,x1,y1,&dc,x0,y0,wxCOPY,FALSE);
266 DoPaint(memdc);
267 // blit it back
268 dc.Blit(x0,y0,x1,y1,&memdc,x0,y0,wxCOPY,FALSE);
269 #endif
270
271 }
272
273 // does the actual painting
274 void
275 wxLayoutWindow::DoPaint(wxDC &dc)
276 {
277 m_llist.EraseAndDraw(dc);
278 m_llist.DrawCursor(dc);
279 // FIXME: not strictly correct, this does only work for changes behind
280 // the cursor position, not complete redraws
281
282 if(! m_ScrollbarsSet)
283 {
284 m_ScrollbarsSet = true; // avoid recursion
285 UpdateScrollbars();
286 }
287 }
288
289 void
290 wxLayoutWindow::UpdateScrollbars(void)
291 {
292 CoordType
293 max_x, max_y, lineHeight;
294
295 ViewStart(&m_ViewStartX, &m_ViewStartY);
296 m_llist.GetSize(&max_x, &max_y, &lineHeight);
297 SetScrollbars(10, lineHeight, max_x/10+1, max_y/lineHeight+1,m_ViewStartX,m_ViewStartY,true);
298 //EnableScrolling(true,true);
299 //Scroll(m_ViewStartX, m_ViewStartY);
300 }
301
302 void
303 wxLayoutWindow::Print(void)
304 {
305 wxPostScriptDC dc("layout.ps",true,this);
306 if (dc.Ok() && dc.StartDoc((char *)_("Printing message...")))
307 {
308 //dc.SetUserScale(1.0, 1.0);
309 m_llist.Draw(dc);
310 dc.EndDoc();
311 }
312 }
313
314 wxMenu *
315 wxLayoutWindow::MakeFormatMenu()
316 {
317 if(m_PopupMenu)
318 return m_PopupMenu;
319
320 wxMenu *m = new wxMenu();
321
322 m->Append(WXLOWIN_MENU_LARGER ,_("&Larger"),_("Switch to larger font."), false);
323 m->Append(WXLOWIN_MENU_SMALLER ,_("&Smaller"),_("Switch to smaller font."), false);
324 m->AppendSeparator();
325 m->Append(WXLOWIN_MENU_UNDERLINE,_("&Underline"),_("Toggle underline mode."), true);
326 m->Append(WXLOWIN_MENU_BOLD ,_("&Bold"),_("Toggle bold mode."), true);
327 m->Append(WXLOWIN_MENU_ITALICS ,_("&Italics"),_("Toggle italics mode."), true);
328 m->AppendSeparator();
329 m->Append(WXLOWIN_MENU_ROMAN ,_("&Roman"),_("Toggle underline mode."), false);
330 m->Append(WXLOWIN_MENU_TYPEWRITER,_("&Typewriter"),_("Toggle bold mode."), false);
331 m->Append(WXLOWIN_MENU_SANSSERIF ,_("&Sans Serif"),_("Toggle italics mode."), false);
332
333 return m_PopupMenu = m;
334 }
335
336 void wxLayoutWindow::OnMenu(wxCommandEvent& event)
337 {
338 if(! m_llist.IsEditable())
339 return;
340
341 switch (event.GetId())
342 {
343 case WXLOWIN_MENU_LARGER:
344 m_llist.SetFontLarger();
345 break;
346 case WXLOWIN_MENU_SMALLER:
347 m_llist.SetFontSmaller();
348 break;
349 case WXLOWIN_MENU_UNDERLINE:
350 m_llist.SetFontUnderline(
351 m_PopupMenu->IsChecked(WXLOWIN_MENU_UNDERLINE) ? false : true
352 );
353 break;
354 case WXLOWIN_MENU_BOLD:
355 m_llist.SetFontWeight(
356 m_PopupMenu->IsChecked(WXLOWIN_MENU_BOLD) ? wxNORMAL : wxBOLD
357 );
358 case WXLOWIN_MENU_ITALICS:
359 m_llist.SetFontStyle(
360 m_PopupMenu->IsChecked(WXLOWIN_MENU_ITALICS) ? wxNORMAL : wxITALIC
361 );
362 break;
363 case WXLOWIN_MENU_ROMAN:
364 m_llist.SetFontFamily(wxROMAN); break;
365 case WXLOWIN_MENU_TYPEWRITER:
366 m_llist.SetFontFamily(wxFIXED); break;
367 case WXLOWIN_MENU_SANSSERIF:
368 m_llist.SetFontFamily(wxSWISS); break;
369 }
370 }