MSW fixes for wxLayout, part II: now breaking and merging line works too.
Scrolling still doesn't :-( git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2662 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
239bca2e6d
commit
bcf4a975e4
@ -38,7 +38,7 @@ IMPLEMENT_APP(MyApp)
|
||||
ID_PRINT_SETUP_PS, ID_PAGE_SETUP_PS,ID_PREVIEW_PS,
|
||||
ID_WRAP, ID_NOWRAP, ID_PASTE, ID_COPY, ID_CUT, ID_FIND,
|
||||
ID_WXLAYOUT_DEBUG, ID_QUIT, ID_CLICK, ID_HTML, ID_TEXT,
|
||||
ID_TEST, ID_LONG_TEST };
|
||||
ID_TEST, ID_LINEBREAKS_TEST, ID_LONG_TEST, ID_URL_TEST };
|
||||
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
|
||||
@ -59,7 +59,8 @@ IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
|
||||
|
||||
|
||||
MyFrame::MyFrame(void) :
|
||||
wxFrame( (wxFrame *) NULL, -1, (char *) "wxLayout", wxPoint(20,20), wxSize(600,360) )
|
||||
wxFrame( (wxFrame *) NULL, -1, "wxLayout",
|
||||
wxPoint(880,100), wxSize(256,256) )
|
||||
{
|
||||
CreateStatusBar( 2 );
|
||||
|
||||
@ -80,24 +81,27 @@ MyFrame::MyFrame(void) :
|
||||
file_menu->Append(ID_PREVIEW_PS, "Print Preview PostScript", "Preview (PostScript)");
|
||||
#endif
|
||||
file_menu->AppendSeparator();
|
||||
file_menu->Append( ID_TEXT, "Export Text");
|
||||
file_menu->Append( ID_HTML, "Export HTML");
|
||||
file_menu->Append( ID_QUIT, "Exit");
|
||||
menu_bar->Append(file_menu, "File" );
|
||||
file_menu->Append( ID_TEXT, "Export &Text");
|
||||
file_menu->Append( ID_HTML, "Export &HTML");
|
||||
file_menu->Append( ID_QUIT, "E&xit");
|
||||
menu_bar->Append(file_menu, "&File" );
|
||||
|
||||
wxMenu *edit_menu = new wxMenu;
|
||||
edit_menu->Append( ID_CLEAR, "Clear");
|
||||
edit_menu->Append( ID_ADD_SAMPLE, "Example");
|
||||
edit_menu->Append( ID_LONG_TEST, "Add many lines");
|
||||
edit_menu->Append( ID_CLEAR, "C&lear");
|
||||
edit_menu->Append( ID_ADD_SAMPLE, "&Example");
|
||||
edit_menu->Append( ID_LONG_TEST, "Add &many lines");
|
||||
edit_menu->AppendSeparator();
|
||||
edit_menu->Append(ID_WRAP, "Wrap mode", "Activate wrapping at pixel 200.");
|
||||
edit_menu->Append(ID_NOWRAP, "No-wrap mode", "Deactivate wrapping.");
|
||||
edit_menu->Append( ID_LINEBREAKS_TEST, "Add &several lines");
|
||||
edit_menu->Append( ID_URL_TEST, "Insert an &URL");
|
||||
edit_menu->AppendSeparator();
|
||||
edit_menu->Append(ID_COPY, "Copy", "Copy text to clipboard.");
|
||||
edit_menu->Append(ID_CUT, "Cut", "Cut text to clipboard.");
|
||||
edit_menu->Append(ID_PASTE,"Paste", "Paste text from clipboard.");
|
||||
edit_menu->Append(ID_FIND, "Find", "Find text.");
|
||||
menu_bar->Append(edit_menu, "Edit" );
|
||||
edit_menu->Append(ID_WRAP, "&Wrap mode", "Activate wrapping at pixel 200.");
|
||||
edit_menu->Append(ID_NOWRAP, "&No-wrap mode", "Deactivate wrapping.");
|
||||
edit_menu->AppendSeparator();
|
||||
edit_menu->Append(ID_COPY, "&Copy", "Copy text to clipboard.");
|
||||
edit_menu->Append(ID_CUT, "Cu&t", "Cut text to clipboard.");
|
||||
edit_menu->Append(ID_PASTE,"&Paste", "Paste text from clipboard.");
|
||||
edit_menu->Append(ID_FIND, "&Find", "Find text.");
|
||||
menu_bar->Append(edit_menu, "&Edit" );
|
||||
|
||||
#ifndef __WXMSW__
|
||||
menu_bar->Show( TRUE );
|
||||
@ -191,8 +195,7 @@ MyFrame::AddSampleText(wxLayoutList *llist)
|
||||
fgets(buffer,1024,in);
|
||||
if(feof(in))
|
||||
break;
|
||||
llist->Insert(buffer);
|
||||
llist->LineBreak();
|
||||
wxLayoutImportText(llist, buffer);
|
||||
}
|
||||
}
|
||||
llist->MoveCursorTo(wxPoint(0,0));
|
||||
@ -300,6 +303,19 @@ void MyFrame::OnCommand( wxCommandEvent &event )
|
||||
m_lwin->Refresh();
|
||||
break;
|
||||
}
|
||||
|
||||
case ID_LINEBREAKS_TEST:
|
||||
wxLayoutImportText(m_lwin->GetLayoutList(),
|
||||
"This is a text\n"
|
||||
"with embedded line\n"
|
||||
"breaks.\n");
|
||||
break;
|
||||
|
||||
case ID_URL_TEST:
|
||||
// VZ: this doesn't work, of course, but I think it should -
|
||||
// wxLayoutWindow should have a flag m_highlightUrls and do it itself
|
||||
// (instead of doing it manually like M does now)
|
||||
m_lwin->GetLayoutList()->Insert("http://www.wxwindows.org/");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -75,7 +75,7 @@
|
||||
// waste time looking for it right now. Search for occurences of
|
||||
// MSW_CORRECTION to find all the places where I did it.
|
||||
#ifdef __WXMSW__
|
||||
static const int MSW_CORRECTION = 10;
|
||||
static const int MSW_CORRECTION = 5;
|
||||
#else
|
||||
static const int MSW_CORRECTION = 0;
|
||||
#endif
|
||||
@ -278,10 +278,16 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
|
||||
{
|
||||
long descent = 0l;
|
||||
|
||||
// now this is done in wxLayoutLine::Layout(), but this code might be
|
||||
// reenabled later - in principle, it's more efficient
|
||||
#if 0
|
||||
CoordType widthOld = m_Width,
|
||||
heightOld = m_Height;
|
||||
#endif // 0
|
||||
|
||||
dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent);
|
||||
|
||||
#if 0
|
||||
if ( widthOld != m_Width || heightOld != m_Height )
|
||||
{
|
||||
// as the text length changed, it must be refreshed
|
||||
@ -302,6 +308,7 @@ wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
|
||||
llist->SetUpdateRect(position.x + widthOld + MSW_CORRECTION,
|
||||
position.y + heightOld + MSW_CORRECTION);
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
m_Bottom = descent;
|
||||
m_Top = m_Height - m_Bottom;
|
||||
@ -582,7 +589,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist)
|
||||
m_LineNumber = 0;
|
||||
m_Width = m_Height = 0;
|
||||
m_Length = 0;
|
||||
m_Dirty = true;
|
||||
MarkDirty(0);
|
||||
m_Previous = prev;
|
||||
m_Next = NULL;
|
||||
RecalculatePosition(llist);
|
||||
@ -610,6 +617,8 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
|
||||
{
|
||||
wxASSERT(m_Previous || GetLineNumber() == 0);
|
||||
|
||||
wxPoint posOld(m_Position);
|
||||
|
||||
if(m_Previous)
|
||||
{
|
||||
m_Position = m_Previous->GetPosition();
|
||||
@ -617,7 +626,18 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist)
|
||||
}
|
||||
else
|
||||
m_Position = wxPoint(0,0);
|
||||
llist->SetUpdateRect(m_Position);
|
||||
|
||||
if ( m_Position != posOld )
|
||||
{
|
||||
// the whole line moved and must be repainted
|
||||
llist->SetUpdateRect(m_Position);
|
||||
llist->SetUpdateRect(m_Position.x + GetWidth() + MSW_CORRECTION,
|
||||
m_Position.y + GetHeight() + MSW_CORRECTION);
|
||||
llist->SetUpdateRect(posOld);
|
||||
llist->SetUpdateRect(posOld.x + GetWidth() + MSW_CORRECTION,
|
||||
posOld.y + GetHeight() + MSW_CORRECTION);
|
||||
}
|
||||
|
||||
return m_Position;
|
||||
}
|
||||
|
||||
@ -740,11 +760,8 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
|
||||
wxASSERT(xpos >= 0);
|
||||
wxASSERT(obj != NULL);
|
||||
|
||||
// in any case, the object is going to belong to this line
|
||||
obj->AttachToLine(this);
|
||||
MarkDirty(xpos);
|
||||
|
||||
//FIXME: this could be optimised, for now be prudent:
|
||||
m_Dirty = true;
|
||||
CoordType offset;
|
||||
wxLOiterator i = FindObject(xpos, &offset);
|
||||
if(i == NULLIT)
|
||||
@ -796,11 +813,12 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
|
||||
}
|
||||
|
||||
bool
|
||||
wxLayoutLine::Insert(CoordType xpos, wxString text)
|
||||
wxLayoutLine::Insert(CoordType xpos, const wxString& text)
|
||||
{
|
||||
wxASSERT(xpos >= 0);
|
||||
//FIXME: this could be optimised, for now be prudent:
|
||||
m_Dirty = true;
|
||||
|
||||
MarkDirty(xpos);
|
||||
|
||||
CoordType offset;
|
||||
wxLOiterator i = FindObject(xpos, &offset);
|
||||
if(i != NULLIT && (**i).GetType() == WXLO_TYPE_TEXT)
|
||||
@ -808,11 +826,14 @@ wxLayoutLine::Insert(CoordType xpos, wxString text)
|
||||
wxLayoutObjectText *tobj = (wxLayoutObjectText *) *i;
|
||||
tobj->GetText().insert(offset, text);
|
||||
m_Length += text.Length();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return Insert(xpos, new wxLayoutObjectText(text));
|
||||
{
|
||||
if ( !Insert(xpos, new wxLayoutObjectText(text)) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CoordType
|
||||
@ -822,8 +843,7 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
|
||||
|
||||
wxASSERT(xpos >= 0);
|
||||
wxASSERT(npos >= 0);
|
||||
//FIXME: this could be optimised, for now be prudent:
|
||||
m_Dirty = true;
|
||||
MarkDirty(xpos);
|
||||
wxLOiterator i = FindObject(xpos, &offset);
|
||||
while(npos > 0)
|
||||
{
|
||||
@ -878,8 +898,7 @@ wxLayoutLine::DeleteWord(CoordType xpos)
|
||||
{
|
||||
wxASSERT(xpos >= 0);
|
||||
CoordType offset;
|
||||
//FIXME: this could be optimised, for now be prudent:
|
||||
m_Dirty = true;
|
||||
MarkDirty(xpos);
|
||||
|
||||
wxLOiterator i = FindObject(xpos, &offset);
|
||||
|
||||
@ -984,23 +1003,29 @@ wxLayoutLine::Layout(wxDC &dc,
|
||||
{
|
||||
wxLayoutObjectList::iterator i;
|
||||
|
||||
// when a line becomes dirty, we redraw it from the place where it was
|
||||
// changed till the end of line (because the following wxLayoutObjects are
|
||||
// moved when the preceding one changes) - calculate the update rectangle.
|
||||
CoordType updateTop = m_Position.y,
|
||||
updateLeft = -1,
|
||||
updateWidth = m_Width,
|
||||
updateHeight = m_Height;
|
||||
|
||||
CoordType
|
||||
oldWidth = m_Width,
|
||||
oldHeight = m_Height;
|
||||
topHeight = 0,
|
||||
bottomHeight = 0; // above and below baseline
|
||||
CoordType
|
||||
topHeight, bottomHeight; // above and below baseline
|
||||
CoordType
|
||||
objHeight = 0,
|
||||
objTopHeight, objBottomHeight;
|
||||
objTopHeight, objBottomHeight; // above and below baseline
|
||||
CoordType
|
||||
len, count = 0;
|
||||
m_Height = 0; m_BaseLine = 0;
|
||||
m_Width = 0;
|
||||
topHeight = 0; bottomHeight = 0;
|
||||
wxPoint size;
|
||||
bool cursorFound = false;
|
||||
|
||||
m_Dirty = false;
|
||||
CoordType heightOld = m_Height;
|
||||
|
||||
m_Height = 0;
|
||||
m_Width = 0;
|
||||
m_BaseLine = 0;
|
||||
|
||||
bool cursorFound = false;
|
||||
|
||||
if(cursorPos)
|
||||
{
|
||||
@ -1013,15 +1038,17 @@ wxLayoutLine::Layout(wxDC &dc,
|
||||
//llist->ApplyStyle(&m_StyleInfo, dc);
|
||||
for(i = m_ObjectList.begin(); i != NULLIT; i++)
|
||||
{
|
||||
(**i).Layout(dc, llist);
|
||||
size = (**i).GetSize(&objTopHeight, &objBottomHeight);
|
||||
wxLayoutObject *obj = *i;
|
||||
obj->Layout(dc, llist);
|
||||
wxPoint sizeObj = obj->GetSize(&objTopHeight, &objBottomHeight);
|
||||
|
||||
if(cursorPos && ! cursorFound)
|
||||
{ // we need to check whether the text cursor is here
|
||||
len = (**i).GetLength();
|
||||
{
|
||||
// we need to check whether the text cursor is here
|
||||
len = obj->GetLength();
|
||||
if(count <= cx && count+len > cx)
|
||||
{
|
||||
if((**i).GetType() == WXLO_TYPE_TEXT)
|
||||
if(obj->GetType() == WXLO_TYPE_TEXT)
|
||||
{
|
||||
len = cx - count; // pos in object
|
||||
CoordType width, height, descent;
|
||||
@ -1030,7 +1057,7 @@ wxLayoutLine::Layout(wxDC &dc,
|
||||
cursorPos->x += width;
|
||||
cursorPos->y = m_Position.y;
|
||||
wxString str;
|
||||
if(len < (**i).GetLength())
|
||||
if(len < obj->GetLength())
|
||||
str = (*(wxLayoutObjectText*)*i).GetText().substr(len,1);
|
||||
else
|
||||
str = WXLO_CURSORCHAR;
|
||||
@ -1038,15 +1065,16 @@ wxLayoutLine::Layout(wxDC &dc,
|
||||
wxASSERT(cursorSize);
|
||||
// Just in case some joker inserted an empty string object:
|
||||
if(width == 0) width = WXLO_MINIMUM_CURSOR_WIDTH;
|
||||
if(height == 0) height = objHeight;
|
||||
if(height == 0) height = sizeObj.y;
|
||||
cursorSize->x = width;
|
||||
cursorSize->y = height;
|
||||
cursorFound = true; // no more checks
|
||||
}
|
||||
else
|
||||
{ // on some other object
|
||||
{
|
||||
// on some other object
|
||||
CoordType top, bottom; // unused
|
||||
*cursorSize = (**i).GetSize(&top,&bottom);
|
||||
*cursorSize = obj->GetSize(&top,&bottom);
|
||||
cursorPos->y = m_Position.y;
|
||||
cursorFound = true; // no more checks
|
||||
}
|
||||
@ -1054,28 +1082,43 @@ wxLayoutLine::Layout(wxDC &dc,
|
||||
else
|
||||
{
|
||||
count += len;
|
||||
cursorPos->x += (**i).GetWidth();
|
||||
cursorPos->x += obj->GetWidth();
|
||||
}
|
||||
} // cursor finding
|
||||
objHeight = size.y;
|
||||
m_Width += size.x;
|
||||
if(objHeight > m_Height) m_Height = objHeight;
|
||||
if(objTopHeight > topHeight) topHeight = objTopHeight;
|
||||
if(objBottomHeight > bottomHeight) bottomHeight = objBottomHeight;
|
||||
|
||||
m_Width += sizeObj.x;
|
||||
if(sizeObj.y > m_Height)
|
||||
{
|
||||
m_Height = sizeObj.y;
|
||||
}
|
||||
|
||||
if(objTopHeight > topHeight)
|
||||
topHeight = objTopHeight;
|
||||
if(objBottomHeight > bottomHeight)
|
||||
bottomHeight = objBottomHeight;
|
||||
}
|
||||
|
||||
// special case of a line which becomes empty (after deletion, for example):
|
||||
// we should invalidate the screen space it occupied (usually this happens
|
||||
// from wxLayoutObject::Layout called in the loop above)
|
||||
if ( m_ObjectList.empty() )
|
||||
if ( IsDirty() )
|
||||
{
|
||||
wxPoint position(GetPosition());
|
||||
llist->SetUpdateRect(position.x + oldWidth + MSW_CORRECTION,
|
||||
position.y + oldHeight + MSW_CORRECTION);
|
||||
if ( updateHeight < m_Height )
|
||||
updateHeight = m_Height;
|
||||
if ( updateWidth < m_Width )
|
||||
updateWidth = m_Width;
|
||||
|
||||
// update all line if we don't know where to start from
|
||||
if ( updateLeft == -1 )
|
||||
updateLeft = 0;
|
||||
|
||||
llist->SetUpdateRect(updateLeft, updateTop);
|
||||
llist->SetUpdateRect(updateLeft + updateWidth + MSW_CORRECTION,
|
||||
updateTop + updateHeight + MSW_CORRECTION);
|
||||
}
|
||||
|
||||
if(topHeight + bottomHeight > m_Height)
|
||||
{
|
||||
m_Height = topHeight+bottomHeight;
|
||||
}
|
||||
|
||||
m_BaseLine = topHeight;
|
||||
|
||||
if(m_Height == 0)
|
||||
@ -1086,10 +1129,12 @@ wxLayoutLine::Layout(wxDC &dc,
|
||||
m_BaseLine = m_Height - descent;
|
||||
}
|
||||
|
||||
|
||||
// tell next line about coordinate change
|
||||
if(m_Next && objHeight != oldHeight)
|
||||
if(m_Next && m_Height != heightOld)
|
||||
{
|
||||
// FIXME isn't this done in RecalculatePositions() below anyhow?
|
||||
m_Next->RecalculatePositions(0, llist);
|
||||
}
|
||||
|
||||
// We need to check whether we found a valid cursor size:
|
||||
if(cursorPos)
|
||||
@ -1106,7 +1151,10 @@ wxLayoutLine::Layout(wxDC &dc,
|
||||
if(m_BaseLine >= cursorSize->y) // the normal case anyway
|
||||
cursorPos->y += m_BaseLine-cursorSize->y;
|
||||
}
|
||||
|
||||
RecalculatePositions(1, llist);
|
||||
|
||||
MarkClean();
|
||||
}
|
||||
|
||||
|
||||
@ -1114,8 +1162,8 @@ wxLayoutLine *
|
||||
wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
|
||||
{
|
||||
wxASSERT(xpos >= 0);
|
||||
//FIXME: this could be optimised, for now be prudent:
|
||||
m_Dirty = true;
|
||||
|
||||
MarkDirty(xpos);
|
||||
|
||||
/* If we are at the begin of a line, we want to move all other
|
||||
lines down and stay with the cursor where we are. However, if we
|
||||
@ -1157,13 +1205,17 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist)
|
||||
i++; // don't move this object to the new list
|
||||
}
|
||||
else
|
||||
{
|
||||
if(offset > 0)
|
||||
i++; // move objects from here to new list
|
||||
}
|
||||
|
||||
while(i != m_ObjectList.end())
|
||||
{
|
||||
newLine->Append(*i);
|
||||
m_Length -= (**i).GetLength();
|
||||
wxLayoutObject *obj = *i;
|
||||
newLine->Append(obj);
|
||||
m_Length -= obj->GetLength();
|
||||
|
||||
m_ObjectList.remove(i); // remove without deleting it
|
||||
}
|
||||
if(m_Next)
|
||||
@ -1178,8 +1230,8 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
|
||||
wxCHECK_RET(GetNextLine(),"wxLayout internal error: no next line to merge");
|
||||
wxLayoutObjectList &list = GetNextLine()->m_ObjectList;
|
||||
wxLOiterator i;
|
||||
//FIXME: this could be optimised, for now be prudent:
|
||||
m_Dirty = true;
|
||||
|
||||
MarkDirty(GetWidth());
|
||||
|
||||
wxLayoutObject *last = NULL;
|
||||
for(i = list.begin(); i != list.end();)
|
||||
@ -1200,7 +1252,6 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
|
||||
else
|
||||
{
|
||||
// just append the object "as was"
|
||||
current->UnattachFromLine();
|
||||
Append(current);
|
||||
|
||||
list.remove(i); // remove without deleting it
|
||||
@ -1211,13 +1262,24 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
|
||||
wxLayoutLine *oldnext = GetNextLine();
|
||||
wxLayoutLine *nextLine = oldnext->GetNextLine();
|
||||
SetNext(nextLine);
|
||||
delete oldnext;
|
||||
if ( nextLine )
|
||||
{
|
||||
nextLine->MoveLines(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is now done in Delete(), but if this function is ever called
|
||||
// from elsewhere, we might have to move refresh code back here (in
|
||||
// order not to duplicate it)
|
||||
#if 0
|
||||
wxPoint pos(oldnext->GetPosition());
|
||||
llist->SetUpdateRect(pos);
|
||||
llist->SetUpdateRect(pos.x + oldnext->GetWidth() + MSW_CORRECTION,
|
||||
pos.y + oldnext->GetHeight() + MSW_CORRECTION);
|
||||
#endif // 0
|
||||
}
|
||||
|
||||
// no RecalculatePositions needed - called from Delete() anyhow
|
||||
delete oldnext;
|
||||
}
|
||||
|
||||
CoordType
|
||||
@ -1613,12 +1675,20 @@ bool
|
||||
wxLayoutList::Insert(wxString const &text)
|
||||
{
|
||||
wxASSERT(m_CursorLine);
|
||||
wxASSERT_MSG( text.Find('\n') == wxNOT_FOUND, "use wxLayoutImportText!" );
|
||||
|
||||
if ( !text )
|
||||
return true;
|
||||
|
||||
AddCursorPosToUpdateRect();
|
||||
|
||||
m_CursorLine->Insert(m_CursorPos.x, text);
|
||||
if ( !m_CursorLine->Insert(m_CursorPos.x, text) )
|
||||
return false;
|
||||
|
||||
m_CursorPos.x += text.Length();
|
||||
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
|
||||
|
||||
m_CursorLine->RecalculatePositions(0, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1634,7 +1704,9 @@ wxLayoutList::Insert(wxLayoutObject *obj)
|
||||
|
||||
m_CursorLine->Insert(m_CursorPos.x, obj);
|
||||
m_CursorPos.x += obj->GetLength();
|
||||
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
|
||||
|
||||
m_CursorLine->RecalculatePositions(0, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1710,7 +1782,9 @@ wxLayoutList::WrapLine(CoordType column)
|
||||
LineBreak();
|
||||
Delete(1); // delete the space
|
||||
m_CursorPos.x = newpos;
|
||||
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
|
||||
|
||||
m_CursorLine->RecalculatePositions(1, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1762,9 +1836,19 @@ wxLayoutList::Delete(CoordType npos)
|
||||
wasMerged = true;
|
||||
wxLayoutLine *next = m_CursorLine->GetNextLine();
|
||||
if ( next )
|
||||
{
|
||||
totalHeight += next->GetHeight();
|
||||
m_CursorLine->MergeNextLine(this);
|
||||
left--;
|
||||
totalWidth += next->GetWidth();
|
||||
|
||||
m_CursorLine->MergeNextLine(this);
|
||||
left--;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG("can't delete all this");
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1776,6 +1860,7 @@ wxLayoutList::Delete(CoordType npos)
|
||||
if ( wasMerged )
|
||||
{
|
||||
wxPoint position(m_CursorLine->GetPosition());
|
||||
SetUpdateRect(position);
|
||||
SetUpdateRect(position.x + totalWidth + MSW_CORRECTION,
|
||||
position.y + totalHeight + MSW_CORRECTION);
|
||||
}
|
||||
@ -1850,11 +1935,13 @@ wxLayoutList::GetCursorScreenPos(wxDC &dc)
|
||||
void
|
||||
wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
|
||||
{
|
||||
wxLayoutLine *line = m_FirstLine;
|
||||
|
||||
// first, make sure everything is calculated - this might not be
|
||||
// needed, optimise it later
|
||||
ApplyStyle(&m_DefaultSetting, dc);
|
||||
|
||||
// FIXME this is completely wrong - we should start by first *visible* line
|
||||
// (and stop on the last one) instead of looping over all lines!!
|
||||
wxLayoutLine *line = m_FirstLine;
|
||||
while(line)
|
||||
{
|
||||
if(forceAll || line->IsDirty())
|
||||
@ -1865,10 +1952,13 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
|
||||
(wxPoint *)&m_CursorSize, m_CursorPos.x);
|
||||
else
|
||||
line->Layout(dc, this);
|
||||
// little condition to speed up redrawing:
|
||||
if(bottom != -1 && line->GetPosition().y > bottom) break;
|
||||
|
||||
// little condition to speed up redrawing:
|
||||
if(bottom != -1 && line->GetPosition().y > bottom)
|
||||
break;
|
||||
}
|
||||
line->RecalculatePositions(1,this);
|
||||
|
||||
line->RecalculatePositions(1, this);
|
||||
line = line->GetNextLine();
|
||||
}
|
||||
|
||||
@ -1924,14 +2014,22 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos,
|
||||
wxLayoutLine *line = m_FirstLine;
|
||||
wxPoint p;
|
||||
|
||||
// we need to run a layout here to get font sizes right :-(
|
||||
ApplyStyle(&m_DefaultSetting, dc);
|
||||
while(line)
|
||||
{
|
||||
p = line->GetPosition();
|
||||
if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y)
|
||||
break;
|
||||
#if 0
|
||||
// we need to run a layout here to get font sizes right :-(
|
||||
|
||||
// VZ: we can't call Layout() from here because it marks the line as
|
||||
// clean and it is not refreshed when it's called from wxLayoutList::
|
||||
// Layout() - if we really need to do this, we should introduce an
|
||||
// extra argument to Layout() to prevent the line from MarkClean()ing
|
||||
// itself here
|
||||
line->Layout(dc, this);
|
||||
#endif
|
||||
line = line->GetNextLine();
|
||||
}
|
||||
if(line == NULL)
|
||||
|
@ -162,7 +162,7 @@ public:
|
||||
virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const { return 0; }
|
||||
|
||||
/// constructor
|
||||
wxLayoutObject() { m_UserData = NULL; m_Line = NULL; }
|
||||
wxLayoutObject() { m_UserData = NULL; }
|
||||
/// delete the user data
|
||||
virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
|
||||
|
||||
@ -183,20 +183,6 @@ public:
|
||||
m_UserData->IncRef();
|
||||
}
|
||||
|
||||
/// returns the line we belong to (or NULL)
|
||||
wxLayoutLine *GetLine() const { return m_Line; }
|
||||
|
||||
/// attaches this object to the given line, it's an error to reattach us
|
||||
void AttachToLine(wxLayoutLine *line)
|
||||
{
|
||||
wxASSERT_MSG( !m_Line, "this layout object already belongs to a line" );
|
||||
|
||||
m_Line = line;
|
||||
}
|
||||
|
||||
/// unattaches the object (should reattach it immediately afterwards!)
|
||||
void UnattachFromLine() { if ( m_Line ) m_Line = (wxLayoutLine *)NULL; }
|
||||
|
||||
/** Return the user data.
|
||||
Increments the object's reference count. When no longer needed,
|
||||
caller must call DecRef() on the pointer returned.
|
||||
@ -221,9 +207,6 @@ public:
|
||||
protected:
|
||||
/// optional data for application's use
|
||||
UserData *m_UserData;
|
||||
|
||||
/// the line of the text we belong to or NULL if we're not shown on screen
|
||||
wxLayoutLine *m_Line;
|
||||
};
|
||||
|
||||
/// Define a list type of wxLayoutObject pointers.
|
||||
@ -472,7 +455,7 @@ public:
|
||||
@param text the text to insert
|
||||
@return true if that xpos existed and the object was inserted
|
||||
*/
|
||||
bool Insert(CoordType xpos, wxString text);
|
||||
bool Insert(CoordType xpos, const wxString& text);
|
||||
|
||||
/** This function appends an object to the line.
|
||||
@param obj the object to insert
|
||||
@ -481,7 +464,6 @@ public:
|
||||
{
|
||||
wxASSERT(obj);
|
||||
|
||||
obj->AttachToLine(this);
|
||||
m_ObjectList.push_back(obj);
|
||||
m_Length += obj->GetLength();
|
||||
}
|
||||
@ -665,7 +647,19 @@ public:
|
||||
/// Returns dirty state
|
||||
bool IsDirty(void) const { return m_Dirty; }
|
||||
/// Marks line as diry.
|
||||
void MarkDirty(void) { m_Dirty = true; }
|
||||
void MarkDirty(CoordType left = -1)
|
||||
{
|
||||
if ( left != -1 )
|
||||
{
|
||||
if ( m_updateLeft == -1 || left < m_updateLeft )
|
||||
m_updateLeft = left;
|
||||
}
|
||||
|
||||
m_Dirty = true;
|
||||
}
|
||||
/// Reset the dirty flag
|
||||
void MarkClean() { m_Dirty = false; m_updateLeft = -1; }
|
||||
|
||||
private:
|
||||
/// Destructor is private. Use DeleteLine() to remove it.
|
||||
~wxLayoutLine();
|
||||
@ -706,6 +700,8 @@ private:
|
||||
wxLayoutObjectList m_ObjectList;
|
||||
/// Have we been changed since the last layout?
|
||||
bool m_Dirty;
|
||||
/// The coordinate of the left boundary of the update rectangle (if m_Dirty)
|
||||
CoordType m_updateLeft;
|
||||
/// Pointer to previous line if it exists.
|
||||
wxLayoutLine *m_Previous;
|
||||
/// Pointer to next line if it exists.
|
||||
|
@ -28,29 +28,30 @@
|
||||
|
||||
#define BASE_SIZE 12
|
||||
|
||||
inline static bool IsEndOfLine(const char *p, int mode)
|
||||
inline static bool IsEndOfLine(const char *p)
|
||||
{
|
||||
// in addition to Unix EOL convention we also (but not instead) understand
|
||||
// the DOS one under Windows
|
||||
return
|
||||
(mode == WXLO_EXPORT_WITH_CRLF) ?
|
||||
((*p == '\r') && (*(p + 1) == '\n'))
|
||||
:
|
||||
(((*p == '\r') && (*(p + 1) == '\n'))||(*p == '\n'));
|
||||
// the end of line is either just '\n' or "\r\n" - we understand both (even
|
||||
// though the second is used only under DOS/Windows) to be able to import
|
||||
// DOS text files even under Unix
|
||||
return (*p == '\n') || ((*p == '\r') && (*(p + 1) == '\n'));
|
||||
}
|
||||
|
||||
void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
|
||||
void wxLayoutImportText(wxLayoutList *list, wxString const &str)
|
||||
{
|
||||
if(str.Length() == 0)
|
||||
if ( !str )
|
||||
return;
|
||||
char * cptr = (char *)str.c_str(); // string gets changed only temporarily
|
||||
|
||||
// we change the string temporarily inside this function
|
||||
wxString& s = (wxString &)str; // const_cast
|
||||
|
||||
char * cptr = s.GetWriteBuf(s.Len());
|
||||
const char * begin = cptr;
|
||||
char backup;
|
||||
|
||||
|
||||
for(;;)
|
||||
{
|
||||
begin = cptr;
|
||||
while( *cptr && !IsEndOfLine(cptr, withflag) )
|
||||
while( *cptr && !IsEndOfLine(cptr) )
|
||||
cptr++;
|
||||
backup = *cptr;
|
||||
*cptr = '\0';
|
||||
@ -58,7 +59,7 @@ void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
|
||||
*cptr = backup;
|
||||
|
||||
// check if it's the end of this line
|
||||
if ( IsEndOfLine(cptr, withflag) )
|
||||
if ( IsEndOfLine(cptr) )
|
||||
{
|
||||
// if it was "\r\n", skip the following '\n'
|
||||
if ( *cptr == '\r' )
|
||||
@ -69,6 +70,8 @@ void wxLayoutImportText(wxLayoutList *list, wxString const &str, int withflag)
|
||||
break;
|
||||
cptr++;
|
||||
}
|
||||
|
||||
s.UngetWriteBuf();
|
||||
}
|
||||
|
||||
static
|
||||
@ -77,11 +80,11 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
|
||||
{
|
||||
static char buffer[20];
|
||||
wxString html;
|
||||
|
||||
|
||||
wxLayoutStyleInfo *si = cmd.GetStyle();
|
||||
|
||||
int size, sizecount;
|
||||
|
||||
|
||||
html += "<font ";
|
||||
|
||||
if(si->m_fg_valid)
|
||||
@ -97,7 +100,7 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
|
||||
sprintf(buffer,"\"#%02X%02X%02X\"", si->m_bg.Red(),si->m_bg.Green(),si->m_bg.Blue());
|
||||
html += buffer;
|
||||
}
|
||||
|
||||
|
||||
switch(si->family)
|
||||
{
|
||||
case wxSWISS:
|
||||
@ -139,7 +142,7 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
|
||||
|
||||
if(si->style == wxSLANT)
|
||||
si->style = wxITALIC; // the same for html
|
||||
|
||||
|
||||
if((si->style == wxITALIC) && ( (!styleInfo) || (styleInfo->style != wxITALIC)))
|
||||
html += "<i>";
|
||||
else
|
||||
@ -151,9 +154,9 @@ wxString wxLayoutExportCmdAsHTML(wxLayoutObjectCmd const & cmd,
|
||||
else if(si->underline == false && ( styleInfo && styleInfo->underline))
|
||||
html += "</u>";
|
||||
|
||||
|
||||
|
||||
*styleInfo = *si; // update last style info
|
||||
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
@ -165,7 +168,7 @@ wxLayoutExportStatus::wxLayoutExportStatus(wxLayoutList *list)
|
||||
m_line = list->GetFirstLine();
|
||||
m_iterator = m_line->GetFirstObject();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define WXLO_IS_TEXT(type) \
|
||||
@ -179,7 +182,7 @@ wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
|
||||
{
|
||||
wxASSERT(status);
|
||||
wxLayoutExportObject * export;
|
||||
|
||||
|
||||
if(status->m_iterator == NULLIT) // end of line
|
||||
{
|
||||
if(!status->m_line || status->m_line->GetNextLine() == NULL)
|
||||
@ -234,7 +237,7 @@ wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
|
||||
break; // end of list
|
||||
}
|
||||
if(! status->m_line) // reached end of list, fall through
|
||||
break;
|
||||
break;
|
||||
type = (** status->m_iterator).GetType();
|
||||
if(type == WXLO_TYPE_ICON)
|
||||
break;
|
||||
|
@ -18,8 +18,8 @@
|
||||
|
||||
enum wxLayoutExportType
|
||||
{
|
||||
WXLO_EXPORT_TEXT,
|
||||
WXLO_EXPORT_HTML,
|
||||
WXLO_EXPORT_TEXT,
|
||||
WXLO_EXPORT_HTML,
|
||||
WXLO_EXPORT_OBJECT,
|
||||
// this can be caused by empty lines:
|
||||
WXLO_EXPORT_EMPTYLINE
|
||||
@ -62,24 +62,17 @@ struct wxLayoutExportStatus
|
||||
};
|
||||
|
||||
#ifdef OS_WIN
|
||||
/// import text into a wxLayoutList (including linefeeds):
|
||||
void wxLayoutImportText(wxLayoutList *list, wxString const &str,
|
||||
int withflag = WXLO_EXPORT_WITH_CRLF);
|
||||
#define WXLO_DEFAULT_EXPORT_MODE WXLO_EXPORT_WITH_CRLF
|
||||
#else // Unix
|
||||
#define WXLO_DEFAULT_EXPORT_MODE WXLO_EXPORT_WITH_LF_ONLY
|
||||
#endif // Win/Unix
|
||||
|
||||
wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
|
||||
int mode = WXLO_EXPORT_AS_TEXT,
|
||||
int flags =
|
||||
WXLO_EXPORT_WITH_CRLF);
|
||||
#else
|
||||
/// import text into a wxLayoutList (including linefeeds):
|
||||
void wxLayoutImportText(wxLayoutList *list, wxString const &str,
|
||||
int withflag = WXLO_EXPORT_WITH_LF_ONLY);
|
||||
void wxLayoutImportText(wxLayoutList *list, wxString const &str);
|
||||
|
||||
/// export text in a given format
|
||||
wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status,
|
||||
int mode = WXLO_EXPORT_AS_TEXT,
|
||||
int flags =
|
||||
WXLO_EXPORT_WITH_LF_ONLY);
|
||||
#endif
|
||||
int flags = WXLO_DEFAULT_EXPORT_MODE);
|
||||
|
||||
#endif //WXLPARSER_H
|
||||
|
@ -28,10 +28,7 @@
|
||||
# include "gui/wxlparser.h"
|
||||
#else
|
||||
# ifdef __WXMSW__
|
||||
# include <windows.h>
|
||||
# undef FindWindow
|
||||
# undef GetCharWidth
|
||||
# undef StartDoc
|
||||
# include <wx/msw/private.h>
|
||||
# endif
|
||||
|
||||
# include "wxlwindow.h"
|
||||
@ -153,9 +150,13 @@ wxLayoutWindow::MSWGetDlgCode()
|
||||
void
|
||||
wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
|
||||
{
|
||||
wxPaintDC dc( this );
|
||||
wxClientDC dc( this );
|
||||
PrepareDC( dc );
|
||||
SetFocus();
|
||||
if ( eventId != WXLOWIN_MENU_MOUSEMOVE )
|
||||
{
|
||||
// moving the mouse in a window shouldn't give it the focus!
|
||||
SetFocus();
|
||||
}
|
||||
|
||||
wxPoint findPos;
|
||||
findPos.x = dc.DeviceToLogicalX(event.GetX());
|
||||
@ -512,10 +513,13 @@ wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
|
||||
void
|
||||
wxLayoutWindow::DoPaint(const wxRect *updateRect)
|
||||
{
|
||||
#ifdef __WXGTK__
|
||||
#ifndef __WXMSW__
|
||||
InternalPaint(updateRect);
|
||||
#else
|
||||
Refresh(FALSE, updateRect); // Causes bad flicker under wxGTK!!!
|
||||
|
||||
if ( !::UpdateWindow(GetHwnd()) )
|
||||
wxLogLastError("UpdateWindow");
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -876,12 +880,12 @@ void
|
||||
wxLayoutWindow::OnSetFocus(wxFocusEvent &ev)
|
||||
{
|
||||
m_HaveFocus = true;
|
||||
//FIXME: need argument DoPaint(); // to repaint the cursor
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void
|
||||
wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
|
||||
{
|
||||
m_HaveFocus = false;
|
||||
//FIXME: need argument DoPaint(); // to repaint the cursor
|
||||
ev.Skip();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user