]> git.saurik.com Git - wxWidgets.git/blob - user/wxLayout/wxllist.cpp
Another small modification... Sorry for CVS list overloading...
[wxWidgets.git] / user / wxLayout / wxllist.cpp
1 /*-*- c++ -*-********************************************************
2 * wxFTCanvas: a canvas for editing formatted text *
3 * *
4 * (C) 1998 by Karsten Ballüder (Ballueder@usa.net) *
5 * *
6 * $Id$ *
7 *******************************************************************/
8
9 /*
10 - each Object knows its size and how to draw itself
11 - the list is responsible for calculating positions
12 - the draw coordinates for each object are the top left corner
13 - coordinates only get calculated when things get redrawn
14 - during redraw each line gets iterated over twice, first just
15 calculating baselines and positions, second to actually draw it
16 - the cursor position is the position before an object, i.e. if the
17 buffer starts with a text-object, cursor 0,0 is just before the
18 first character
19 */
20
21 #ifdef __GNUG__
22 #pragma implementation "wxllist.h"
23 #endif
24
25 #include "wxllist.h"
26 #include "iostream.h"
27
28 #include <wx/dc.h>
29 #include <wx/postscrp.h>
30 #include <wx/print.h>
31
32 #define BASELINESTRETCH 12
33
34 #ifdef WXLAYOUT_DEBUG
35 static const char *_t[] = { "invalid", "text", "cmd", "icon",
36 "linebreak"};
37
38 void
39 wxLayoutObjectBase::Debug(void)
40 {
41 CoordType bl = 0;
42 cerr << _t[GetType()] << ": size=" << GetSize(&bl).x << ","
43 << GetSize(&bl).y << " bl=" << bl;
44 }
45
46 # define VAR(x) cerr << #x"=" << x << endl;
47 # define DBG_POINT(p) cerr << #p << ": " << p.x << ',' << p.y << endl
48 # define TRACE(f) cerr << #f":" << endl;
49 #else
50 # define VAR(x)
51 # define DBG_POINT(p)
52 # define TRACE(f)
53 #endif
54
55 //-------------------------- wxLayoutObjectText
56
57 wxLayoutObjectText::wxLayoutObjectText(const String &txt)
58 {
59 m_Text = txt;
60 m_Width = 0;
61 m_Height = 0;
62 }
63
64
65 wxPoint
66 wxLayoutObjectText::GetSize(CoordType *baseLine) const
67 {
68 if(baseLine) *baseLine = m_BaseLine;
69 return wxPoint(m_Width, m_Height);
70 }
71
72 void
73 wxLayoutObjectText::Draw(wxDC &dc, wxPoint position, CoordType baseLine,
74 bool draw)
75 {
76 long descent = 0l;
77 dc.GetTextExtent(Str(m_Text),&m_Width, &m_Height, &descent);
78 //FIXME: wxGTK does not set descent to a descent value yet.
79 if(descent == 0)
80 descent = (2*m_Height)/10; // crude fix
81 m_BaseLine = m_Height - descent;
82 position.y += baseLine-m_BaseLine;
83 if(draw)
84 dc.DrawText(Str(m_Text),position.x,position.y);
85 # ifdef WXLAYOUT_DEBUG
86 // dc.DrawRectangle(position.x, position.y, m_Width, m_Height);
87 # endif
88 }
89
90 #ifdef WXLAYOUT_DEBUG
91 void
92 wxLayoutObjectText::Debug(void)
93 {
94 wxLayoutObjectBase::Debug();
95 cerr << " `" << m_Text << '\'';
96 }
97 #endif
98
99 //-------------------------- wxLayoutObjectIcon
100
101 wxLayoutObjectIcon::wxLayoutObjectIcon(wxIcon *icon)
102 {
103 m_Icon = icon;
104 }
105
106 void
107 wxLayoutObjectIcon::Draw(wxDC &dc, wxPoint position, CoordType baseLine,
108 bool draw)
109 {
110 position.y += baseLine - m_Icon->GetHeight();
111 if(draw)
112 dc.DrawIcon(m_Icon,position.x,position.y);
113 }
114
115 wxPoint
116 wxLayoutObjectIcon::GetSize(CoordType *baseLine) const
117 {
118 wxASSERT(baseLine);
119 *baseLine = m_Icon->GetHeight();
120 return wxPoint(m_Icon->GetWidth(), m_Icon->GetHeight());
121 }
122
123 //-------------------------- wxLayoutObjectCmd
124
125
126 wxLayoutObjectCmd::wxLayoutObjectCmd(int size, int family, int style, int
127 weight, bool underline,
128 wxColour const *fg, wxColour const *bg)
129
130 {
131 m_font = new wxFont(size,family,style,weight,underline);
132 m_ColourFG = fg;
133 m_ColourBG = bg;
134 }
135
136 wxLayoutObjectCmd::~wxLayoutObjectCmd()
137 {
138 delete m_font;
139 }
140
141 wxLayoutStyleInfo *
142 wxLayoutObjectCmd::GetStyle(void) const
143 {
144 wxLayoutStyleInfo *si = new wxLayoutStyleInfo();
145
146
147 si->size = m_font->GetPointSize();
148 si->family = m_font->GetFamily();
149 si->style = m_font->GetStyle();
150 si->underline = m_font->GetUnderlined();
151 si->weight = m_font->GetWeight();
152
153 si->fg_red = m_ColourFG->Red();
154 si->fg_green = m_ColourFG->Green();
155 si->fg_blue = m_ColourFG->Blue();
156 si->bg_red = m_ColourBG->Red();
157 si->bg_green = m_ColourBG->Green();
158 si->bg_blue = m_ColourBG->Blue();
159
160 return si;
161 }
162
163 void
164 wxLayoutObjectCmd::Draw(wxDC &dc, wxPoint position, CoordType lineHeight,
165 bool draw)
166 {
167 wxASSERT(m_font);
168 // this get called even when draw==false, so that recalculation
169 // uses right font sizes
170 dc.SetFont(m_font);
171 if(m_ColourFG)
172 dc.SetTextForeground(*m_ColourFG);
173 if(m_ColourBG)
174 dc.SetTextBackground(*m_ColourBG);
175 }
176
177 //-------------------------- wxwxLayoutList
178
179 wxLayoutList::wxLayoutList()
180 {
181 m_DefaultSetting = NULL;
182 Clear();
183 }
184
185 wxLayoutList::~wxLayoutList()
186 {
187 if(m_DefaultSetting)
188 delete m_DefaultSetting;
189 }
190
191
192 void
193 wxLayoutList::LineBreak(void)
194 {
195 Insert(new wxLayoutObjectLineBreak);
196 m_CursorPosition.x = 0; m_CursorPosition.y++;
197 }
198
199 void
200 wxLayoutList::SetFont(int family, int size, int style, int weight,
201 int underline, wxColour const *fg,
202 wxColour const *bg)
203 {
204 if(family != -1) m_FontFamily = family;
205 if(size != -1) m_FontPtSize = size;
206 if(style != -1) m_FontStyle = style;
207 if(weight != -1) m_FontWeight = weight;
208 if(underline != -1) m_FontUnderline = underline;
209
210 if(fg != NULL) m_ColourFG = fg;
211 if(bg != NULL) m_ColourBG = bg;
212
213 Insert(
214 new wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,m_FontWeight,m_FontUnderline,
215 m_ColourFG, m_ColourBG));
216 }
217
218 void
219 wxLayoutList::SetFont(int family, int size, int style, int weight,
220 int underline, char const *fg, char const *bg)
221 {
222 wxColour const
223 * cfg = NULL,
224 * cbg = NULL;
225
226 if( fg )
227 cfg = wxTheColourDatabase->FindColour(fg);
228 if( bg )
229 cbg = wxTheColourDatabase->FindColour(bg);
230
231 SetFont(family,size,style,weight,underline,cfg,cbg);
232 }
233
234
235 /// for access by wxLayoutWindow:
236 void
237 wxLayoutList::GetSize(CoordType *max_x, CoordType *max_y,
238 CoordType *lineHeight)
239 {
240 wxASSERT(max_x); wxASSERT(max_y); wxASSERT(lineHeight);
241 *max_x = m_MaxX;
242 *max_y = m_MaxY;
243 *lineHeight = m_LineHeight;
244 }
245
246 wxLayoutObjectBase *
247 wxLayoutList::Draw(wxDC &dc, bool findObject, wxPoint const &findCoords)
248 {
249 wxLayoutObjectList::iterator i;
250
251 // in case we need to look for an object
252 wxLayoutObjectBase *foundObject = NULL;
253
254 // first object in current line
255 wxLayoutObjectList::iterator headOfLine;
256
257 // do we need to recalculate current line?
258 bool recalculate = false;
259
260 // do we calculate or draw? Either true or false.
261 bool draw = false;
262 // drawing parameters:
263 wxPoint position = wxPoint(0,0);
264 wxPoint position_HeadOfLine;
265 CoordType baseLine = m_FontPtSize;
266 CoordType baseLineSkip = (BASELINESTRETCH * baseLine)/10;
267
268 // we trace the objects' cursor positions so we can draw the cursor
269 wxPoint cursor = wxPoint(0,0);
270 // the cursor position inside the object
271 CoordType cursorOffset = 0;
272 // object under cursor
273 wxLayoutObjectList::iterator cursorObject = FindCurrentObject(&cursorOffset);
274
275 // queried from each object:
276 wxPoint size = wxPoint(0,0);
277 CoordType objBaseLine = baseLine;
278 wxLayoutObjectType type;
279
280 // used temporarily
281 wxLayoutObjectText *tobj = NULL;
282
283
284 // this is needed for printing to a printer:
285 // only interesting for printer/PS output
286 int pageWidth, pageHeight; //GetSize() still needs int at the moment
287 struct
288 {
289 int top, bottom, left, right;
290 } margins;
291
292 if(
293 #ifdef __WXMSW__
294 dc.IsKindOf(CLASSINFO(wxPrinterDC)) ||
295 #endif
296 dc.IsKindOf(CLASSINFO(wxPostScriptDC)))
297 {
298 VAR(wxThePrintSetupData);
299
300 dc.GetSize(&pageWidth, &pageHeight);
301 dc.StartDoc(_("Printing..."));
302 dc.StartPage();
303 margins.top = (1*pageHeight)/10; // 10%
304 margins.bottom = (9*pageHeight)/10; // 90%
305 margins.left = (1*pageWidth)/10;
306 margins.right = (9*pageWidth)/10;
307 }
308 else
309 {
310 margins.top = 0; margins.left = 0;
311 margins.right = -1;
312 margins.bottom = -1;
313 }
314 position.y = margins.right;
315 position.x = margins.left;
316
317 VAR(findObject); VAR(findCoords.x); VAR(findCoords.y);
318 // if the cursorobject is a cmd, we need to find the first
319 // printable object:
320 while(cursorObject != end()
321 && (*cursorObject)->GetType() == WXLO_TYPE_CMD)
322 cursorObject++;
323
324 headOfLine = begin();
325 position_HeadOfLine = position;
326
327 // setting up the default:
328 dc.SetTextForeground( *wxBLACK );
329 dc.SetTextBackground( *wxWHITE );
330 dc.SetBackgroundMode( wxSOLID ); // to enable setting of text background
331 dc.SetFont( *wxNORMAL_FONT );
332
333
334 //FIXME: who frees the brush, how long does it need to exist?
335 if(m_DefaultSetting)
336 m_DefaultSetting->Draw(dc,wxPoint(0,0),0,true);
337
338 // we calculate everything for drawing a line, then rewind to the
339 // begin of line and actually draw it
340 i = begin();
341 for(;;)
342 {
343 recalculate = false;
344
345 if(i == end())
346 break;
347 type = (*i)->GetType();
348
349 // to initialise sizes of objects, we need to call Draw
350 (*i)->Draw(dc, position, baseLine, draw);
351
352 // update coordinates for next object:
353 size = (*i)->GetSize(&objBaseLine);
354 if(findObject && draw) // we need to look for an object
355 {
356 if(findCoords.y >= position.y
357 && findCoords.y <= position.y+size.y
358 && findCoords.x >= position.x
359 && findCoords.x <= position.x+size.x)
360 {
361 foundObject = *i;
362 findObject = false; // speeds things up
363 }
364 }
365 // draw the cursor
366 if(m_Editable && draw && i == cursorObject)
367 {
368 if(type == WXLO_TYPE_TEXT) // special treatment
369 {
370 long descent = 0l; long width, height;
371 tobj = (wxLayoutObjectText *)*i;
372 String str = tobj->GetText();
373 VAR(m_CursorPosition.x); VAR(cursor.x);
374 str = str.substr(0, cursorOffset);
375 VAR(str);
376 dc.GetTextExtent(Str(str), &width,&height, &descent);
377 VAR(height);
378 VAR(width); VAR(descent);
379 if(width < 1) width = 1;
380 dc.DrawLine(position.x+width,
381 position.y+(baseLineSkip-height),
382 position.x+width, position.y+baseLineSkip);
383 }
384 else
385 {
386 if(type == WXLO_TYPE_LINEBREAK)
387 dc.DrawLine(0, position.y+baseLineSkip, 0, position.y+2*baseLineSkip);
388 else
389 {
390 if(size.x == 0)
391 {
392 if(size.y == 0)
393 dc.DrawLine(position.x, position.y, position.x, position.y+baseLineSkip);
394 else
395 dc.DrawLine(position.x, position.y, position.x, position.y+size.y);
396 }
397 else
398 dc.DrawRectangle(position.x, position.y, size.x, size.y);
399 }
400 }
401 }
402
403 // calculate next object's position:
404 position.x += size.x;
405 if(position.x > m_MaxX)
406 m_MaxX = position.x;
407
408 // do we need to increase the line's height?
409 if(size.y > baseLineSkip)
410 {
411 baseLineSkip = size.y;
412 recalculate = true;
413 }
414 if(objBaseLine > baseLine)
415 {
416 baseLine = objBaseLine;
417 recalculate = true;
418 }
419
420 // now check whether we have finished handling this line:
421 if(type == WXLO_TYPE_LINEBREAK || i == tail())
422 {
423 if(recalculate) // do this line again
424 {
425 position.x = position_HeadOfLine.x;
426 i = headOfLine;
427 continue;
428 }
429
430 if(! draw) // finished calculating sizes
431 {
432 // if the this line needs to go onto a new page, we need
433 // to change pages before drawing it:
434 if(margins.bottom != -1 && position.y > margins.bottom)
435 {
436 dc.EndPage();
437 position_HeadOfLine.y = margins.top;
438 dc.StartPage();
439 }
440 // do this line again, this time drawing it
441 position = position_HeadOfLine;
442 draw = true;
443 i = headOfLine;
444 continue;
445 }
446 else // we have drawn a line, so continue calculating next one
447 draw = false;
448 }
449
450 // is it a linebreak?
451 if(type == WXLO_TYPE_LINEBREAK || i == tail())
452 {
453 position.x = margins.left;
454 position.y += baseLineSkip;
455 baseLine = m_FontPtSize;
456 objBaseLine = baseLine; // not all objects set it
457 baseLineSkip = (BASELINESTRETCH * baseLine)/10;
458 headOfLine = i;
459 headOfLine++;
460 position_HeadOfLine = position;
461 }
462 i++;
463 }
464 dc.EndDoc();
465 m_MaxY = position.y;
466 return foundObject;
467 }
468
469 #ifdef WXLAYOUT_DEBUG
470 void
471 wxLayoutList::Debug(void)
472 {
473 CoordType offs;
474 wxLayoutObjectList::iterator i;
475
476 cerr <<
477 "------------------------debug start-------------------------" << endl;
478 for(i = begin(); i != end(); i++)
479 {
480 (*i)->Debug();
481 cerr << endl;
482 }
483 cerr <<
484 "-----------------------debug end----------------------------"
485 << endl;
486 // show current object:
487 cerr << "Cursor: "
488 << m_CursorPosition.x << ','
489 << m_CursorPosition.y;
490
491 i = FindCurrentObject(&offs);
492 cerr << " line length: " << GetLineLength(i) << " ";
493 if(i == end())
494 {
495 cerr << "<<no object found>>" << endl;
496 return; // FIXME we should set cursor position to maximum allowed
497 // value then
498 }
499 if((*i)->GetType() == WXLO_TYPE_TEXT)
500 {
501 cerr << " \"" << ((wxLayoutObjectText *)(*i))->GetText() << "\", offs: "
502 << offs << endl;
503 }
504 else
505 cerr << ' ' << _t[(*i)->GetType()] << endl;
506
507 }
508 #endif
509
510 /******************** editing stuff ********************/
511
512 // don't change this, I know how to optimise this and will do it real
513 // soon (KB)
514
515 wxLayoutObjectList::iterator
516 wxLayoutList::FindObjectCursor(wxPoint const &cpos, CoordType *offset)
517 {
518 wxPoint cursor = wxPoint(0,0); // runs along the objects
519 CoordType width;
520 wxLayoutObjectList::iterator i;
521
522 #ifdef WXLAYOUT_DEBUG
523 cerr << "Looking for object at " << cpos.x << ',' << cpos.y <<
524 endl;
525 #endif
526 for(i = begin(); i != end() && cursor.y <= cpos.y; i++)
527 {
528 width = 0;
529 if((*i)->GetType() == WXLO_TYPE_LINEBREAK)
530 {
531 if(cpos.y == cursor.y && i != begin())
532 {
533 --i;
534 if(offset) *offset = i != end() ? (*i)->CountPositions() : 0;
535 return i;
536 }
537 cursor.x = 0; cursor.y ++;
538 }
539 else
540 cursor.x += (width = (*i)->CountPositions());
541 if(cursor.y == cpos.y && (cursor.x > cpos.x ||
542 ((*i)->GetType() != WXLO_TYPE_CMD && cursor.x == cpos.x))
543 ) // found it ?
544 {
545 if(offset)
546 *offset = cpos.x-(cursor.x-width); // 0==cursor before
547 // the object
548 #ifdef WXLAYOUT_DEBUG
549 cerr << " found object at " << cursor.x-width << ',' <<
550 cursor.y << ", type:" << _t[(*i)->GetType()] <<endl;
551 #endif
552 return i;
553 }
554 }
555 #ifdef WXLAYOUT_DEBUG
556 cerr << " not found" << endl;
557 #endif
558 return end(); // not found
559 }
560
561 wxLayoutObjectList::iterator
562 wxLayoutList::FindCurrentObject(CoordType *offset)
563 {
564 wxLayoutObjectList::iterator obj = end();
565
566 obj = FindObjectCursor(m_CursorPosition, offset);
567 if(obj == end()) // not ideal yet
568 {
569 obj = tail();
570 if(obj != end()) // tail really exists
571 *offset = (*obj)->CountPositions(); // at the end of it
572 }
573 return obj;
574 }
575
576 void
577 wxLayoutList::MoveCursor(int dx, int dy)
578 {
579 CoordType offs, lineLength;
580 wxLayoutObjectList::iterator i;
581
582
583 if(dy > 0 && m_CursorPosition.y < m_MaxLine)
584 m_CursorPosition.y += dy;
585 else if(dy < 0 && m_CursorPosition.y > 0)
586 m_CursorPosition.y += dy; // dy is negative
587 if(m_CursorPosition.y < 0)
588 m_CursorPosition.y = 0;
589 else if (m_CursorPosition.y > m_MaxLine)
590 m_CursorPosition.y = m_MaxLine;
591
592 while(dx > 0)
593 {
594 i = FindCurrentObject(&offs);
595 lineLength = GetLineLength(i);
596 if(m_CursorPosition.x < lineLength)
597 {
598 m_CursorPosition.x ++;
599 dx--;
600 continue;
601 }
602 else
603 {
604 if(m_CursorPosition.y < m_MaxLine)
605 {
606 m_CursorPosition.y++;
607 m_CursorPosition.x = 0;
608 dx--;
609 }
610 else
611 break; // cannot move there
612 }
613 }
614 while(dx < 0)
615 {
616 if(m_CursorPosition.x > 0)
617 {
618 m_CursorPosition.x --;
619 dx++;
620 }
621 else
622 {
623 if(m_CursorPosition.y > 0)
624 {
625 m_CursorPosition.y --;
626 m_CursorPosition.x = 0;
627 i = FindCurrentObject(&offs);
628 lineLength = GetLineLength(i);
629 m_CursorPosition.x = lineLength;
630 dx++;
631 continue;
632 }
633 else
634 break; // cannot move left any more
635 }
636 }
637 // final adjustment:
638 i = FindCurrentObject(&offs);
639 lineLength = GetLineLength(i);
640 if(m_CursorPosition.x > lineLength)
641 m_CursorPosition.x = lineLength;
642
643 #ifdef WXLAYOUT_DEBUG
644 i = FindCurrentObject(&offs);
645 cerr << "Cursor: "
646 << m_CursorPosition.x << ','
647 << m_CursorPosition.y;
648
649 if(i == end())
650 {
651 cerr << "<<no object found>>" << endl;
652 return; // FIXME we should set cursor position to maximum allowed
653 // value then
654 }
655 if((*i)->GetType() == WXLO_TYPE_TEXT)
656 {
657 cerr << " \"" << ((wxLayoutObjectText *)(*i))->GetText() << "\", offs: "
658 << offs << endl;
659 }
660 else
661 cerr << ' ' << _t[(*i)->GetType()] << endl;
662 #endif
663 }
664
665 void
666 wxLayoutList::Delete(CoordType count)
667 {
668 TRACE(Delete);
669
670 if(!m_Editable)
671 return;
672
673 VAR(count);
674
675 CoordType offs, len;
676 wxLayoutObjectList::iterator i;
677
678 do
679 {
680 i = FindCurrentObject(&offs);
681 if(i == end())
682 return;
683 #ifdef WXLAYOUT_DEBUG
684 cerr << "trying to delete: " << _t[(*i)->GetType()] << endl;
685 #endif
686 if((*i)->GetType() == WXLO_TYPE_LINEBREAK)
687 m_MaxLine--;
688 if((*i)->GetType() == WXLO_TYPE_TEXT)
689 {
690 wxLayoutObjectText *tobj = (wxLayoutObjectText *)*i;
691 len = tobj->CountPositions();
692 // If we find the end of a text object, this means that we
693 // have to delete from the object following it.
694 if(offs == len)
695 {
696 i++;
697 if(i != end() && (*i)->GetType() == WXLO_TYPE_TEXT)
698 {
699 offs = 0; // delete from begin of next string
700 tobj = (wxLayoutObjectText *)*i;
701 len = tobj->CountPositions();
702 }
703 else
704 {
705 erase(i);
706 return;
707 }
708 }
709 if(len <= count) // delete this object
710 {
711 count -= len;
712 erase(i);
713 }
714 else
715 {
716 len = count;
717 VAR(offs); VAR(len);
718 tobj->GetText().erase(offs,len);
719 return; // we are done
720 }
721 }
722 else // delete the object
723 {
724 len = (*i)->CountPositions();
725 erase(i); // after this, i is the iterator for the following object
726 if(count > len)
727 count -= len;
728 else
729 count = 0;
730 }
731 }
732 while(count && i != end());
733 }
734
735 void
736 wxLayoutList::Insert(wxLayoutObjectBase *obj)
737 {
738 wxASSERT(obj);
739 CoordType offs;
740 wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
741
742 TRACE(Insert(obj));
743
744 if(i == end())
745 push_back(obj);
746 else
747 {
748 // do we have to split a text object?
749 if((*i)->GetType() == WXLO_TYPE_TEXT && offs != 0 && offs != (*i)->CountPositions())
750 {
751 wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
752 #ifdef WXLAYOUT_DEBUG
753 cerr << "text: '" << tobj->GetText() << "'" << endl;
754 VAR(offs);
755 #endif
756 String left = tobj->GetText().substr(0,offs); // get part before cursor
757 VAR(left);
758 tobj->GetText() = tobj->GetText().substr(offs,(*i)->CountPositions()-offs); // keeps the right half
759 VAR(tobj->GetText());
760 insert(i,obj);
761 insert(i,new wxLayoutObjectText(left)); // inserts before
762 }
763 else
764 {
765 wxLayoutObjectList::iterator j = i; // we want to apend after this object
766 j++;
767 if(j != end())
768 insert(j, obj);
769 else
770 push_back(obj);
771 }
772 }
773 m_CursorPosition.x += obj->CountPositions();
774 if(obj->GetType() == WXLO_TYPE_LINEBREAK)
775 m_MaxLine++;
776 }
777
778 void
779 wxLayoutList::Insert(String const &text)
780 {
781 wxLayoutObjectText *tobj = NULL;
782 TRACE(Insert(text));
783
784 if(! m_Editable)
785 return;
786
787 CoordType offs;
788 wxLayoutObjectList::iterator i = FindCurrentObject(&offs);
789
790 if(i != end() && (*i)->GetType() == WXLO_TYPE_TEXT)
791 { // insert into an existing text object:
792 TRACE(inserting into existing object);
793 tobj = (wxLayoutObjectText *)*i ;
794 wxASSERT(tobj);
795 tobj->GetText().insert(offs,text);
796 }
797 else // check whether the previous object is text:
798 {
799 wxLayoutObjectList::iterator j = i;
800 j--;
801 TRACE(checking previous object);
802 if(0 && j != end() && (*j)->GetType() == WXLO_TYPE_TEXT)
803 {
804 tobj = (wxLayoutObjectText *)*i;
805 wxASSERT(tobj);
806 tobj->GetText()+=text;
807 }
808 else // insert a new text object
809 {
810 TRACE(creating new object);
811 Insert(new wxLayoutObjectText(text)); //FIXME not too optimal, slow
812 return; // position gets incremented in Insert(obj)
813 }
814 }
815 m_CursorPosition.x += strlen(text.c_str());
816 }
817
818 CoordType
819 wxLayoutList::GetLineLength(wxLayoutObjectList::iterator i)
820 {
821 if(i == end())
822 return 0;
823
824 CoordType len = 0;
825
826 // search backwards for beginning of line:
827 while(i != begin() && (*i)->GetType() != WXLO_TYPE_LINEBREAK)
828 i--;
829 if((*i)->GetType() == WXLO_TYPE_LINEBREAK)
830 i++;
831 // now we can start counting:
832 while(i != end() && (*i)->GetType() != WXLO_TYPE_LINEBREAK)
833 {
834 len += (*i)->CountPositions();
835 i++;
836 }
837 return len;
838 }
839
840 void
841 wxLayoutList::Clear(int family, int size, int style, int weight,
842 int underline, char const *fg, char const *bg)
843 {
844 wxLayoutObjectList::iterator i = begin();
845
846 while(i != end()) // == while valid
847 erase(i);
848
849 // set defaults
850 m_FontPtSize = size;
851 m_FontUnderline = false;
852 m_FontFamily = family;
853 m_FontStyle = style;
854 m_FontWeight = weight;
855 m_ColourFG = wxTheColourDatabase->FindColour(fg);
856 m_ColourBG = wxTheColourDatabase->FindColour(bg);
857
858 if(! m_ColourFG) m_ColourFG = wxBLACK;
859 if(! m_ColourBG) m_ColourBG = wxWHITE;
860
861 m_Position = wxPoint(0,0);
862 m_CursorPosition = wxPoint(0,0);
863 m_MaxLine = 0;
864 m_LineHeight = (BASELINESTRETCH*m_FontPtSize)/10;
865 m_MaxX = 0; m_MaxY = 0;
866
867
868 if(m_DefaultSetting)
869 delete m_DefaultSetting;
870 m_DefaultSetting = new
871 wxLayoutObjectCmd(m_FontPtSize,m_FontFamily,m_FontStyle,
872 m_FontWeight,m_FontUnderline,
873 m_ColourFG, m_ColourBG);
874 }