First part of fixes to make this work under MSW.

1. letters actually appear on the screen
2. Clear() works
3. Backspace/Delete in one line works too
4. breaking lines works
5. cursor is now a wxCaret
6. tons of other fixes


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2652 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-06-02 21:26:11 +00:00
parent 379a3b04b9
commit 5bdc3b1d4a
6 changed files with 492 additions and 294 deletions

View File

@@ -61,7 +61,7 @@ IMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame )
MyFrame::MyFrame(void) : MyFrame::MyFrame(void) :
wxFrame( (wxFrame *) NULL, -1, (char *) "wxLayout", wxPoint(20,20), wxSize(600,360) ) wxFrame( (wxFrame *) NULL, -1, (char *) "wxLayout", wxPoint(20,20), wxSize(600,360) )
{ {
CreateStatusBar( 1 ); CreateStatusBar( 2 );
SetStatusText( "wxLayout by Karsten Ball<6C>der." ); SetStatusText( "wxLayout by Karsten Ball<6C>der." );
@@ -106,6 +106,7 @@ MyFrame::MyFrame(void) :
SetMenuBar( menu_bar ); SetMenuBar( menu_bar );
m_lwin = new wxLayoutWindow(this); m_lwin = new wxLayoutWindow(this);
m_lwin->SetStatusBar(GetStatusBar(), 0, 1);
m_lwin->SetMouseTracking(true); m_lwin->SetMouseTracking(true);
m_lwin->SetEditable(true); m_lwin->SetEditable(true);
m_lwin->SetWrapMargin(40); m_lwin->SetWrapMargin(40);

View File

@@ -11,17 +11,17 @@
*/ */
#ifdef __GNUG__ #ifdef __GNUG__
#pragma implementation "wxllist.h" #pragma implementation "wxllist.h"
#endif #endif
#include "Mpch.h" #include <wx/wxprec.h>
#include "wx/wxprec.h"
#ifdef __BORLANDC__ #ifdef __BORLANDC__
# pragma hdrstop # pragma hdrstop
#endif #endif
#include "Mpch.h"
#ifdef M_BASEDIR #ifdef M_BASEDIR
# include "gui/wxllist.h" # include "gui/wxllist.h"
# include "gui/wxlparser.h" # include "gui/wxlparser.h"
@@ -33,14 +33,19 @@
#endif #endif
#ifndef USE_PCH #ifndef USE_PCH
# include "iostream.h" # include <iostream.h>
# include <wx/dc.h>
# include <wx/dcps.h> # include <wx/dc.h>
# include <wx/print.h> # include <wx/dcps.h>
# include <wx/log.h> # include <wx/print.h>
# include <wx/filefn.h> # include <wx/log.h>
# include <wx/filefn.h>
#endif #endif
#ifdef WXLAYOUT_USE_CARET
# include <wx/caret.h>
#endif // WXLAYOUT_USE_CARET
#include <ctype.h> #include <ctype.h>
/// This should never really get created /// This should never really get created
@@ -48,23 +53,32 @@
#ifdef WXLAYOUT_DEBUG #ifdef WXLAYOUT_DEBUG
# define TypewxString(t) g_aTypewxStrings[t] # define TypeString(t) g_aTypeStrings[t]
# define WXLO_DEBUG(x) wxLogDebug x # define WXLO_DEBUG(x) wxLogDebug x
static const char *g_aTypewxStrings[] = static const char *g_aTypeStrings[] =
{ {
"invalid", "text", "cmd", "icon" "invalid", "text", "cmd", "icon"
}; };
void void
wxLayoutObject::Debug(void) wxLayoutObject::Debug(void)
{ {
WXLO_DEBUG(("%s",g_aTypewxStrings[GetType()])); WXLO_DEBUG(("%s",g_aTypeStrings[GetType()]));
} }
#else #else
# define TypewxString(t) "" # define TypeString(t) ""
# define WXLO_DEBUG(x) # define WXLO_DEBUG(x)
#endif #endif
// FIXME under MSW, this constant is needed to make the thing properly redraw
// itself - I don't know where the size calculation error is and I can't
// 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;
#else
static const int MSW_CORRECTION = 0;
#endif
/// Cursors smaller than this disappear in XOR drawing mode /// Cursors smaller than this disappear in XOR drawing mode
#define WXLO_MINIMUM_CURSOR_WIDTH 4 #define WXLO_MINIMUM_CURSOR_WIDTH 4
@@ -73,18 +87,6 @@
#define WXLO_CURSORCHAR "E" #define WXLO_CURSORCHAR "E"
/** @name Helper functions */ /** @name Helper functions */
//@{ //@{
/// allows me to compare to wxPoints
bool operator ==(wxPoint const &p1, wxPoint const &p2)
{
return p1.x == p2.x && p1.y == p2.y;
}
/// allows me to compare to wxPoints
bool operator !=(wxPoint const &p1, wxPoint const &p2)
{
return p1.x != p2.x || p1.y != p2.y;
}
/// allows me to compare to wxPoints /// allows me to compare to wxPoints
bool operator <=(wxPoint const &p1, wxPoint const &p2) bool operator <=(wxPoint const &p1, wxPoint const &p2)
{ {
@@ -272,11 +274,35 @@ wxLayoutObjectText::GetOffsetScreen(wxDC &dc, CoordType xpos) const
} }
void void
wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList * ) wxLayoutObjectText::Layout(wxDC &dc, class wxLayoutList *llist)
{ {
long descent = 0l; long descent = 0l;
dc.GetTextExtent(m_Text,&m_Width, &m_Height, &descent); CoordType widthOld = m_Width,
heightOld = m_Height;
dc.GetTextExtent(m_Text, &m_Width, &m_Height, &descent);
if ( widthOld != m_Width || heightOld != m_Height )
{
// as the text length changed, it must be refreshed
wxLayoutLine *line = GetLine();
wxCHECK_RET( line, "wxLayoutObjectText can't refresh itself" );
// as our size changed, we need to repaint the part which was appended
wxPoint position(line->GetPosition());
// this is not the most efficient way (we repaint the whole line), but
// it's not too slow and is *simple*
if ( widthOld < m_Width )
widthOld = m_Width;
if ( heightOld < m_Height )
heightOld = m_Height;
llist->SetUpdateRect(position.x + widthOld + MSW_CORRECTION,
position.y + heightOld + MSW_CORRECTION);
}
m_Bottom = descent; m_Bottom = descent;
m_Top = m_Height - m_Bottom; m_Top = m_Height - m_Bottom;
} }
@@ -389,7 +415,7 @@ wxLayoutStyleInfo::wxLayoutStyleInfo(int ifamily,
{ {
family = ifamily; size = isize; family = ifamily; size = isize;
style = istyle; weight = iweight; style = istyle; weight = iweight;
underline = iul; underline = iul != 0;
if(fg) if(fg)
{ {
m_fg = *fg; m_fg = *fg;
@@ -713,6 +739,10 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj)
{ {
wxASSERT(xpos >= 0); wxASSERT(xpos >= 0);
wxASSERT(obj != NULL); wxASSERT(obj != NULL);
// in any case, the object is going to belong to this line
obj->AttachToLine(this);
//FIXME: this could be optimised, for now be prudent: //FIXME: this could be optimised, for now be prudent:
m_Dirty = true; m_Dirty = true;
CoordType offset; CoordType offset;
@@ -839,6 +869,7 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos)
((wxLayoutObjectText *)(*i))->GetText().Remove(offset,max); ((wxLayoutObjectText *)(*i))->GetText().Remove(offset,max);
} }
} }
return npos; return npos;
} }
@@ -954,6 +985,7 @@ wxLayoutLine::Layout(wxDC &dc,
wxLayoutObjectList::iterator i; wxLayoutObjectList::iterator i;
CoordType CoordType
oldWidth = m_Width,
oldHeight = m_Height; oldHeight = m_Height;
CoordType CoordType
topHeight, bottomHeight; // above and below baseline topHeight, bottomHeight; // above and below baseline
@@ -1031,8 +1063,19 @@ wxLayoutLine::Layout(wxDC &dc,
if(objTopHeight > topHeight) topHeight = objTopHeight; if(objTopHeight > topHeight) topHeight = objTopHeight;
if(objBottomHeight > bottomHeight) bottomHeight = objBottomHeight; if(objBottomHeight > bottomHeight) bottomHeight = objBottomHeight;
} }
if(topHeight + bottomHeight > m_Height) m_Height =
topHeight+bottomHeight; // 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() )
{
wxPoint position(GetPosition());
llist->SetUpdateRect(position.x + oldWidth + MSW_CORRECTION,
position.y + oldHeight + MSW_CORRECTION);
}
if(topHeight + bottomHeight > m_Height)
m_Height = topHeight+bottomHeight;
m_BaseLine = topHeight; m_BaseLine = topHeight;
if(m_Height == 0) if(m_Height == 0)
@@ -1138,17 +1181,43 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist)
//FIXME: this could be optimised, for now be prudent: //FIXME: this could be optimised, for now be prudent:
m_Dirty = true; m_Dirty = true;
wxLayoutObject *last = NULL;
for(i = list.begin(); i != list.end();) for(i = list.begin(); i != list.end();)
{ {
Append(*i); wxLayoutObject *current = *i;
list.remove(i); // remove without deleting it
// merge text objects together for efficiency
if ( last && last->GetType() == WXLO_TYPE_TEXT &&
current->GetType() == WXLO_TYPE_TEXT )
{
wxLayoutObjectText *textObj = (wxLayoutObjectText *)last;
wxString text(textObj->GetText());
text += ((wxLayoutObjectText *)current)->GetText();
textObj->SetText(text);
list.erase(i); // remove and delete it
}
else
{
// just append the object "as was"
current->UnattachFromLine();
Append(current);
list.remove(i); // remove without deleting it
}
} }
wxASSERT(list.empty()); wxASSERT(list.empty());
wxLayoutLine *oldnext = GetNextLine(); wxLayoutLine *oldnext = GetNextLine();
SetNext(GetNextLine()->GetNextLine()); wxLayoutLine *nextLine = oldnext->GetNextLine();
SetNext(nextLine);
delete oldnext; delete oldnext;
GetNextLine()->MoveLines(-1); if ( nextLine )
RecalculatePositions(1, llist); {
nextLine->MoveLines(-1);
}
// no RecalculatePositions needed - called from Delete() anyhow
} }
CoordType CoordType
@@ -1297,6 +1366,10 @@ wxLayoutLine::Copy(wxLayoutList *llist,
wxLayoutList::wxLayoutList() wxLayoutList::wxLayoutList()
{ {
#ifdef WXLAYOUT_USE_CARET
m_caret = NULL;
#endif // WXLAYOUT_USE_CARET
m_FirstLine = NULL; m_FirstLine = NULL;
InvalidateUpdateRect(); InvalidateUpdateRect();
Clear(); Clear();
@@ -1418,8 +1491,8 @@ wxLayoutList::FindText(const wxString &needle, const wxPoint &cpos) const
bool bool
wxLayoutList::MoveCursorTo(wxPoint const &p) wxLayoutList::MoveCursorTo(wxPoint const &p)
{ {
SetUpdateRect(m_CursorScreenPos); AddCursorPosToUpdateRect();
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
wxLayoutLine *line = m_FirstLine; wxLayoutLine *line = m_FirstLine;
while(line && line->GetLineNumber() != p.y) while(line && line->GetLineNumber() != p.y)
line = line->GetNextLine(); line = line->GetNextLine();
@@ -1445,8 +1518,8 @@ wxLayoutList::MoveCursorTo(wxPoint const &p)
bool bool
wxLayoutList::MoveCursorVertically(int n) wxLayoutList::MoveCursorVertically(int n)
{ {
SetUpdateRect(m_CursorScreenPos); AddCursorPosToUpdateRect();
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
bool rc; bool rc;
if(n < 0) // move up if(n < 0) // move up
{ {
@@ -1499,8 +1572,8 @@ wxLayoutList::MoveCursorVertically(int n)
bool bool
wxLayoutList::MoveCursorHorizontally(int n) wxLayoutList::MoveCursorHorizontally(int n)
{ {
SetUpdateRect(m_CursorScreenPos); AddCursorPosToUpdateRect();
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
int move; int move;
while(n < 0) while(n < 0)
{ {
@@ -1540,8 +1613,9 @@ bool
wxLayoutList::Insert(wxString const &text) wxLayoutList::Insert(wxString const &text)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize); AddCursorPosToUpdateRect();
m_CursorLine->Insert(m_CursorPos.x, text); m_CursorLine->Insert(m_CursorPos.x, text);
m_CursorPos.x += text.Length(); m_CursorPos.x += text.Length();
m_CursorLine->RecalculatePositions(true, this); //FIXME needed? m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
@@ -1552,9 +1626,12 @@ bool
wxLayoutList::Insert(wxLayoutObject *obj) wxLayoutList::Insert(wxLayoutObject *obj)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
if(! m_CursorLine) m_CursorLine = GetFirstLine();
SetUpdateRect(m_CursorScreenPos); if(! m_CursorLine)
SetUpdateRect(m_CursorScreenPos+m_CursorSize); m_CursorLine = GetFirstLine();
AddCursorPosToUpdateRect();
m_CursorLine->Insert(m_CursorPos.x, obj); m_CursorLine->Insert(m_CursorPos.x, obj);
m_CursorPos.x += obj->GetLength(); m_CursorPos.x += obj->GetLength();
m_CursorLine->RecalculatePositions(true, this); //FIXME needed? m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
@@ -1581,16 +1658,19 @@ wxLayoutList::Insert(wxLayoutList *llist)
return rc; return rc;
} }
bool bool
wxLayoutList::LineBreak(void) wxLayoutList::LineBreak(void)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0); bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0);
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize); AddCursorPosToUpdateRect();
wxPoint position(m_CursorLine->GetPosition());
wxCoord width = m_CursorLine->GetWidth(),
height = m_CursorLine->GetHeight();
m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this); m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this);
if(setFirst) // we were at beginning of first line if(setFirst) // we were at beginning of first line
m_FirstLine = m_CursorLine->GetPreviousLine(); m_FirstLine = m_CursorLine->GetPreviousLine();
@@ -1598,7 +1678,16 @@ wxLayoutList::LineBreak(void)
m_CursorPos.y++; m_CursorPos.y++;
m_CursorPos.x = 0; m_CursorPos.x = 0;
// doesn't help m_CursorLine.MarkDirty(); // doesn't help m_CursorLine.MarkDirty();
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
wxLayoutLine *prev = m_CursorLine->GetPreviousLine();
wxCHECK_MSG(prev, false, "just broke the line, where is the previous one?");
height += prev->GetHeight();
SetUpdateRect(position);
SetUpdateRect(position.x + width + MSW_CORRECTION,
position.y + height + MSW_CORRECTION);
return true; return true;
} }
@@ -1615,8 +1704,9 @@ wxLayoutList::WrapLine(CoordType column)
//else: //else:
CoordType newpos = m_CursorPos.x - xpos - 1; CoordType newpos = m_CursorPos.x - xpos - 1;
m_CursorPos.x = xpos; m_CursorPos.x = xpos;
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize); AddCursorPosToUpdateRect();
LineBreak(); LineBreak();
Delete(1); // delete the space Delete(1); // delete the space
m_CursorPos.x = newpos; m_CursorPos.x = newpos;
@@ -1628,41 +1718,68 @@ wxLayoutList::WrapLine(CoordType column)
bool bool
wxLayoutList::Delete(CoordType npos) wxLayoutList::Delete(CoordType npos)
{ {
wxASSERT(m_CursorLine); wxCHECK_MSG(m_CursorLine, false, "can't delete in non existing line");
SetUpdateRect(m_CursorScreenPos); wxASSERT_MSG(npos > 0, "nothing to delete?");
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
AddCursorPosToUpdateRect();
// were other lines appended to this one (this is important to know because
// this means that our width _increased_ as the result of deletion)
bool wasMerged = false;
// the size of the region to update
CoordType totalHeight = m_CursorLine->GetHeight(),
totalWidth = m_CursorLine->GetWidth();
CoordType left; CoordType left;
do do
{ {
left = m_CursorLine->Delete(m_CursorPos.x, npos); left = m_CursorLine->Delete(m_CursorPos.x, npos);
if(left == 0)
return true; if( left > 0 )
// More to delete, continue on next line. {
// First, check if line is empty: // More to delete, continue on next line.
if(m_CursorLine->GetLength() == 0)
{ // in this case, updating could probably be optimised // First, check if line is empty:
if(m_CursorLine->GetLength() == 0)
{
// in this case, updating could probably be optimised
#ifdef WXLO_DEBUG #ifdef WXLO_DEBUG
wxASSERT(DeleteLines(1) == 0); wxASSERT(DeleteLines(1) == 0);
#else #else
DeleteLines(1); DeleteLines(1);
#endif #endif
left--; left--;
} }
else
{
// Need to join next line
if(! m_CursorLine->GetNextLine())
break; // cannot
else else
{ {
m_CursorLine->MergeNextLine(this); // Need to join next line
left--; if(! m_CursorLine->GetNextLine())
break; // cannot
else
{
wasMerged = true;
wxLayoutLine *next = m_CursorLine->GetNextLine();
if ( next )
totalHeight += next->GetHeight();
m_CursorLine->MergeNextLine(this);
left--;
}
} }
} }
} }
while(left); while ( left> 0 );
m_CursorLine->RecalculatePositions(true, this); //FIXME needed?
// we need to update the whole tail of the line and the lines which
// disappeared
if ( wasMerged )
{
wxPoint position(m_CursorLine->GetPosition());
SetUpdateRect(position.x + totalWidth + MSW_CORRECTION,
position.y + totalHeight + MSW_CORRECTION);
}
return left == 0; return left == 0;
} }
@@ -1671,8 +1788,9 @@ wxLayoutList::DeleteLines(int n)
{ {
wxASSERT(m_CursorLine); wxASSERT(m_CursorLine);
wxLayoutLine *line; wxLayoutLine *line;
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize); AddCursorPosToUpdateRect();
while(n > 0) while(n > 0)
{ {
if(!m_CursorLine->GetNextLine()) if(!m_CursorLine->GetNextLine())
@@ -1761,8 +1879,7 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll)
m_CursorLine->GetNextLine() == NULL && m_CursorLine->GetNextLine() == NULL &&
m_CursorLine == m_FirstLine)); m_CursorLine == m_FirstLine));
#endif #endif
SetUpdateRect(m_CursorScreenPos); AddCursorPosToUpdateRect();
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
} }
void void
@@ -1859,10 +1976,8 @@ wxLayoutList::GetSize(void) const
void void
wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate) wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
{ {
wxPoint coords; wxPoint coords(m_CursorScreenPos);
coords = m_CursorScreenPos; coords += translate;
coords.x += translate.x;
coords.y += translate.y;
#ifdef WXLAYOUT_DEBUG #ifdef WXLAYOUT_DEBUG
WXLO_DEBUG(("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld", WXLO_DEBUG(("Drawing cursor (%ld,%ld) at %ld,%ld, size %ld,%ld, line: %ld, len %ld",
@@ -1871,8 +1986,13 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
(long)m_CursorSize.x, (long)m_CursorSize.y, (long)m_CursorSize.x, (long)m_CursorSize.y,
(long)m_CursorLine->GetLineNumber(), (long)m_CursorLine->GetLineNumber(),
(long)m_CursorLine->GetLength())); (long)m_CursorLine->GetLength()));
wxLogStatus("Cursor is at (%d, %d)", m_CursorPos.x, m_CursorPos.y);
#endif #endif
#ifdef WXLAYOUT_USE_CARET
m_caret->Move(coords);
#else // !WXLAYOUT_USE_CARET
dc.SetBrush(*wxBLACK_BRUSH); dc.SetBrush(*wxBLACK_BRUSH);
dc.SetLogicalFunction(wxXOR); dc.SetLogicalFunction(wxXOR);
dc.SetPen(wxPen(*wxBLACK,1,wxSOLID)); dc.SetPen(wxPen(*wxBLACK,1,wxSOLID));
@@ -1892,6 +2012,7 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate)
} }
dc.SetLogicalFunction(wxCOPY); dc.SetLogicalFunction(wxCOPY);
//dc.SetBrush(wxNullBrush); //dc.SetBrush(wxNullBrush);
#endif // WXLAYOUT_USE_CARET/!WXLAYOUT_USE_CARET
} }
void void
@@ -2173,6 +2294,7 @@ wxLayoutList::GetSelection(wxLayoutDataObject *wxlo, bool invalidate)
export->content.object->Write(string); export->content.object->Write(string);
delete export; delete export;
} }
wxlo->SetData(string.c_str(), string.Length()+1); wxlo->SetData(string.c_str(), string.Length()+1);
} }
return llist; return llist;

View File

@@ -30,6 +30,12 @@
# define WXMENU_LAYOUT_DBLCLICK 1113 # define WXMENU_LAYOUT_DBLCLICK 1113
#endif #endif
// use the wxWindows caret class instead of home grown cursor whenever possible
#ifdef __WXMSW__
#undef WXLAYOUT_USE_CARET
#define WXLAYOUT_USE_CARET 1
#endif // __WXMSW__
// do not enable debug mode within Mahogany // do not enable debug mode within Mahogany
#if defined(__WXDEBUG__) && ! defined(M_BASEDIR) #if defined(__WXDEBUG__) && ! defined(M_BASEDIR)
# define WXLAYOUT_DEBUG # define WXLAYOUT_DEBUG
@@ -72,11 +78,13 @@ typedef long CoordType;
// Forward declarations. // Forward declarations.
class wxLayoutList; class wxLayoutList;
class wxLayoutLine;
class wxLayoutObject; class wxLayoutObject;
class wxDC;
class wxColour;
class wxFont;
class WXDLLEXPORT wxCaret;
class WXDLLEXPORT wxColour;
class WXDLLEXPORT wxDC;
class WXDLLEXPORT wxFont;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
@@ -118,7 +126,7 @@ public:
@param dc the wxDC to draw on @param dc the wxDC to draw on
@param llist the wxLayoutList @param llist the wxLayoutList
*/ */
virtual void Layout(wxDC &dc, class wxLayoutList *llist) = 0; virtual void Layout(wxDC &dc, wxLayoutList *llist) = 0;
/** Draws an object. /** Draws an object.
@param dc the wxDC to draw on @param dc the wxDC to draw on
@@ -129,7 +137,7 @@ public:
*/ */
virtual void Draw(wxDC & /* dc */, virtual void Draw(wxDC & /* dc */,
wxPoint const & /* coords */, wxPoint const & /* coords */,
class wxLayoutList *wxllist, wxLayoutList *wxllist,
CoordType begin = -1, CoordType begin = -1,
CoordType end = -1) { } CoordType end = -1) { }
@@ -154,7 +162,7 @@ public:
virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const { return 0; } virtual CoordType GetOffsetScreen(wxDC &dc, CoordType xpos) const { return 0; }
/// constructor /// constructor
wxLayoutObject() { m_UserData = NULL; } wxLayoutObject() { m_UserData = NULL; m_Line = NULL; }
/// delete the user data /// delete the user data
virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); } virtual ~wxLayoutObject() { if(m_UserData) m_UserData->DecRef(); }
@@ -175,6 +183,20 @@ public:
m_UserData->IncRef(); 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. /** Return the user data.
Increments the object's reference count. When no longer needed, Increments the object's reference count. When no longer needed,
caller must call DecRef() on the pointer returned. caller must call DecRef() on the pointer returned.
@@ -199,6 +221,9 @@ public:
protected: protected:
/// optional data for application's use /// optional data for application's use
UserData *m_UserData; 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. /// Define a list type of wxLayoutObject pointers.
@@ -222,9 +247,9 @@ public:
wxLayoutObjectText(const wxString &txt = ""); wxLayoutObjectText(const wxString &txt = "");
virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_TEXT; } virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_TEXT; }
virtual void Layout(wxDC &dc, class wxLayoutList *llist); virtual void Layout(wxDC &dc, wxLayoutList *llist);
virtual void Draw(wxDC &dc, wxPoint const &coords, virtual void Draw(wxDC &dc, wxPoint const &coords,
class wxLayoutList *wxllist, wxLayoutList *wxllist,
CoordType begin = -1, CoordType begin = -1,
CoordType end = -1); CoordType end = -1);
/** Calculates and returns the size of the object. /** Calculates and returns the size of the object.
@@ -284,9 +309,9 @@ public:
~wxLayoutObjectIcon() { if(m_Icon) delete m_Icon; } ~wxLayoutObjectIcon() { if(m_Icon) delete m_Icon; }
virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_ICON; } virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_ICON; }
virtual void Layout(wxDC &dc, class wxLayoutList *llist); virtual void Layout(wxDC &dc, wxLayoutList *llist);
virtual void Draw(wxDC &dc, wxPoint const &coords, virtual void Draw(wxDC &dc, wxPoint const &coords,
class wxLayoutList *wxllist, wxLayoutList *wxllist,
CoordType begin = -1, CoordType begin = -1,
CoordType end = -1); CoordType end = -1);
@@ -372,7 +397,8 @@ public:
bool underline); bool underline);
wxFont & GetFont(wxLayoutStyleInfo const &si) wxFont & GetFont(wxLayoutStyleInfo const &si)
{ {
return GetFont(si.family, si.size, si.style, si.weight, si.underline); return GetFont(si.family, si.size, si.style, si.weight,
si.underline != 0);
} }
private: private:
wxFCEList m_FontList; wxFCEList m_FontList;
@@ -389,9 +415,9 @@ class wxLayoutObjectCmd : public wxLayoutObject
{ {
public: public:
virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_CMD; } virtual wxLayoutObjectType GetType(void) const { return WXLO_TYPE_CMD; }
virtual void Layout(wxDC &dc, class wxLayoutList *llist); virtual void Layout(wxDC &dc, wxLayoutList *llist);
virtual void Draw(wxDC &dc, wxPoint const &coords, virtual void Draw(wxDC &dc, wxPoint const &coords,
class wxLayoutList *wxllist, wxLayoutList *wxllist,
CoordType begin = -1, CoordType begin = -1,
CoordType end = -1); CoordType end = -1);
wxLayoutObjectCmd(int family = -1, wxLayoutObjectCmd(int family = -1,
@@ -419,9 +445,6 @@ private:
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/// forward declaration
class wxLayoutList;
/** This class represents a single line of objects to be displayed. /** This class represents a single line of objects to be displayed.
It knows its height and total size and whether it needs to be It knows its height and total size and whether it needs to be
redrawn or not. redrawn or not.
@@ -457,6 +480,8 @@ public:
void Append(wxLayoutObject * obj) void Append(wxLayoutObject * obj)
{ {
wxASSERT(obj); wxASSERT(obj);
obj->AttachToLine(this);
m_ObjectList.push_back(obj); m_ObjectList.push_back(obj);
m_Length += obj->GetLength(); m_Length += obj->GetLength();
} }
@@ -711,6 +736,11 @@ public:
/// Destructor. /// Destructor.
~wxLayoutList(); ~wxLayoutList();
#ifdef WXLAYOUT_USE_CARET
/// give us the pointer to the caret to use
void SetCaret(wxCaret *caret) { m_caret = caret; }
#endif // WXLAYOUT_USE_CARET
/// Clear the list. /// Clear the list.
void Clear(int family = wxROMAN, void Clear(int family = wxROMAN,
int size=WXLO_DEFAULTFONTSIZE, int size=WXLO_DEFAULTFONTSIZE,
@@ -944,6 +974,15 @@ public:
*/ */
inline void SetUpdateRect(const wxPoint &p) inline void SetUpdateRect(const wxPoint &p)
{ SetUpdateRect(p.x,p.y); } { SetUpdateRect(p.x,p.y); }
/// adds the cursor position to the update rectangle
void AddCursorPosToUpdateRect()
{
#ifndef WXLAYOUT_USE_CARET
SetUpdateRect(m_CursorScreenPos);
SetUpdateRect(m_CursorScreenPos+m_CursorSize);
//#else - the caret will take care of refreshing itself
#endif // !WXLAYOUT_USE_CARET
}
/// Invalidates the update rectangle. /// Invalidates the update rectangle.
void InvalidateUpdateRect(void) { m_UpdateRectValid = false; } void InvalidateUpdateRect(void) { m_UpdateRectValid = false; }
/// Returns the update rectangle. /// Returns the update rectangle.
@@ -1018,12 +1057,16 @@ private:
//@{ //@{
/// Where the text cursor (column,line) is. /// Where the text cursor (column,line) is.
wxPoint m_CursorPos; wxPoint m_CursorPos;
/// The size of the cursor.
wxPoint m_CursorSize;
/// Where the cursor should be drawn. /// Where the cursor should be drawn.
wxPoint m_CursorScreenPos; wxPoint m_CursorScreenPos;
/// The line where the cursor is. /// The line where the cursor is.
wxLayoutLine *m_CursorLine; wxLayoutLine *m_CursorLine;
/// The size of the cursor.
wxPoint m_CursorSize;
#ifdef WXLAYOUT_USE_CARET
/// the caret
wxCaret *m_caret;
#endif // WXLAYOUT_USE_CARET
//@} //@}
/// A structure for the selection. /// A structure for the selection.
@@ -1045,7 +1088,6 @@ private:
//@} //@}
}; };
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
The wxLayoutDataObject for exporting data to the clipboard in our The wxLayoutDataObject for exporting data to the clipboard in our

View File

@@ -10,7 +10,14 @@
# pragma implementation "wxlparser.h" # pragma implementation "wxlparser.h"
#endif #endif
#include <wx/wxprec.h>
#ifdef __BORLANDC__
# pragma hdrstop
#endif
#include "Mpch.h" #include "Mpch.h"
#ifdef M_PREFIX #ifdef M_PREFIX
# include "gui/wxllist.h" # include "gui/wxllist.h"
# include "gui/wxlparser.h" # include "gui/wxlparser.h"

View File

@@ -11,12 +11,13 @@
#endif #endif
#include "wx/wxprec.h" #include "wx/wxprec.h"
#ifdef __BORLANDC__ #ifdef __BORLANDC__
# pragma hdrstop # pragma hdrstop
#endif #endif
#include "Mpch.h" #include "Mpch.h"
#ifdef M_BASEDIR #ifdef M_BASEDIR
# ifndef USE_PCH # ifndef USE_PCH
# include "Mcommon.h" # include "Mcommon.h"
@@ -41,6 +42,10 @@
#include <wx/textctrl.h> #include <wx/textctrl.h>
#include <wx/dataobj.h> #include <wx/dataobj.h>
#ifdef WXLAYOUT_USE_CARET
# include <wx/caret.h>
#endif // WXLAYOUT_USE_CARET
#include <ctype.h> #include <ctype.h>
#ifdef WXLAYOUT_DEBUG #ifdef WXLAYOUT_DEBUG
@@ -71,8 +76,9 @@ BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
END_EVENT_TABLE() END_EVENT_TABLE()
wxLayoutWindow::wxLayoutWindow(wxWindow *parent) wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
: wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize, : wxScrolledWindow(parent, -1,
wxHSCROLL | wxVSCROLL | wxBORDER) wxDefaultPosition, wxDefaultSize,
wxHSCROLL | wxVSCROLL | wxBORDER)
{ {
SetStatusBar(NULL); // don't use statusbar SetStatusBar(NULL); // don't use statusbar
@@ -85,6 +91,7 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
m_bitmap = new wxBitmap(4,4); m_bitmap = new wxBitmap(4,4);
m_bitmapSize = wxPoint(4,4); m_bitmapSize = wxPoint(4,4);
m_llist = new wxLayoutList(); m_llist = new wxLayoutList();
m_BGbitmap = NULL; m_BGbitmap = NULL;
m_ScrollToCursor = false; m_ScrollToCursor = false;
SetWrapMargin(0); SetWrapMargin(0);
@@ -93,6 +100,15 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
EnableScrolling(true,true); EnableScrolling(true,true);
m_maxx = max.x; m_maxy = max.y; m_maxx = max.x; m_maxy = max.y;
m_Selecting = false; m_Selecting = false;
#ifdef WXLAYOUT_USE_CARET
// FIXME cursor size shouldn't be hardcoded
wxCaret *caret = new wxCaret(this, 2, 20);
SetCaret(caret);
m_llist->SetCaret(caret);
caret->Show();
#endif // WXLAYOUT_USE_CARET
SetCursorVisibility(-1); SetCursorVisibility(-1);
SetCursor(wxCURSOR_IBEAM); SetCursor(wxCURSOR_IBEAM);
SetDirty(); SetDirty();
@@ -121,12 +137,8 @@ wxLayoutWindow::Clear(int family,
ResizeScrollbars(true); ResizeScrollbars(true);
SetDirty(); SetDirty();
SetModified(false); SetModified(false);
wxRect r;
int w,h; DoPaint((wxRect *)NULL);
r.x = r.y = 0; GetSize(&w,&h);
r.width = w;
r.height = h;
DoPaint(&r);
} }
#ifdef __WXMSW__ #ifdef __WXMSW__
@@ -323,7 +335,10 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
break; break;
default: default:
if(keyCode == 'c' && event.ControlDown()) if(keyCode == 'c' && event.ControlDown())
{
// this should work even in read-only mode
Copy(); Copy();
}
if( IsEditable() ) if( IsEditable() )
{ {
/* First, handle control keys */ /* First, handle control keys */
@@ -353,9 +368,6 @@ wxLayoutWindow::OnChar(wxKeyEvent& event)
case 'v': case 'v':
Paste(); Paste();
break; break;
case 'c':
Copy();
break;
case 'x': case 'x':
Cut(); Cut();
break; break;
@@ -513,6 +525,11 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
wxPaintDC dc( this ); wxPaintDC dc( this );
PrepareDC( dc ); PrepareDC( dc );
#ifdef WXLAYOUT_USE_CARET
// hide the caret before drawing anything
GetCaret()->Hide();
#endif // WXLAYOUT_USE_CARET
int x0,y0,x1,y1, dx, dy; int x0,y0,x1,y1, dx, dy;
// Calculate where the top of the visible area is: // Calculate where the top of the visible area is:
@@ -604,7 +621,7 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
// update rectangle (although they are drawn on the memDC, this is // update rectangle (although they are drawn on the memDC, this is
// needed to erase it): // needed to erase it):
m_llist->InvalidateUpdateRect(); m_llist->InvalidateUpdateRect();
if(m_CursorVisibility == 1) if(m_CursorVisibility != 0)
m_llist->DrawCursor(*m_memDC, m_llist->DrawCursor(*m_memDC,
m_HaveFocus && IsEditable(), // draw a thick m_HaveFocus && IsEditable(), // draw a thick
// cursor for editable windows with focus // cursor for editable windows with focus
@@ -636,12 +653,19 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect)
dc.Blit(x0,y0,x1,y1,m_memDC,0,0,wxCOPY,FALSE); dc.Blit(x0,y0,x1,y1,m_memDC,0,0,wxCOPY,FALSE);
} }
#ifdef WXLAYOUT_USE_CARET
// show the caret back after everything is redrawn
m_caret->Show();
#endif // WXLAYOUT_USE_CARET
ResetDirty(); ResetDirty();
m_ScrollToCursor = false; m_ScrollToCursor = false;
if(m_StatusBar && m_StatusFieldCursor != -1) if(m_StatusBar && m_StatusFieldCursor != -1)
{ {
wxString label; wxString label;
label.Printf(_("L:%d C:%d"), m_llist->GetCursorPos().x+1, m_llist->GetCursorPos().y+1); label.Printf(_("Ln:%d Col:%d"),
m_llist->GetCursorPos().y+1,
m_llist->GetCursorPos().x+1);
m_StatusBar->SetStatusText(label, m_StatusFieldCursor); m_StatusBar->SetStatusText(label, m_StatusFieldCursor);
} }
} }
@@ -698,6 +722,7 @@ wxLayoutWindow::Paste(void)
} }
wxTheClipboard->Close(); wxTheClipboard->Close();
} }
#if 0 #if 0
/* My attempt to get the primary selection, but it does not /* My attempt to get the primary selection, but it does not
work. :-( */ work. :-( */
@@ -758,6 +783,7 @@ wxLayoutWindow::Copy(bool invalidate)
wxTheClipboard->Close(); wxTheClipboard->Close();
return rc; return rc;
} }
return FALSE; return FALSE;
} }

View File

@@ -23,7 +23,7 @@
#endif #endif
#define wxUSE_PRIVATE_CLIPBOARD_FORMAT 0 #define wxUSE_PRIVATE_CLIPBOARD_FORMAT 1
enum enum
{ {