From: Vadim Zeitlin Date: Tue, 25 May 1999 18:01:48 +0000 (+0000) Subject: wxCaret now exists not only under MSW but on any supported platform as well X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/0290598f588681eb631c0a952a26c7637b8482d0 wxCaret now exists not only under MSW but on any supported platform as well git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2564 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/caret.h b/include/wx/caret.h index 1c10856e42..e88f6c96ca 100644 --- a/include/wx/caret.h +++ b/include/wx/caret.h @@ -19,10 +19,16 @@ class WXDLLEXPORT wxWindow; class WXDLLEXPORT wxWindowBase; -// --------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// headers we have to include +// ---------------------------------------------------------------------------- + +#include "wx/gdicmn.h" // for wxPoint, wxSize + +// ---------------------------------------------------------------------------- // A caret is a blinking cursor showing the position where the typed text will // appear. It can be either a solid block or a custom bitmap (TODO) -// --------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- class WXDLLEXPORT wxCaretBase { @@ -63,6 +69,9 @@ public: // is the caret valid? bool IsOk() const { return m_width != 0 && m_height != 0; } + // is the caret currently shown? + bool IsVisible() const { return m_countVisible > 0; } + // get the caret position void GetPosition(int *x, int *y) const { @@ -167,11 +176,10 @@ private: // now include the real thing // --------------------------------------------------------------------------- -#ifdef __WXMSW__ +#if defined(__WXMSW__) #include "wx/msw/caret.h" #else - // not implemented yet - typedef wxCaretBase wxCaret; + #include "wx/generic/caret.h" #endif // platform #endif // _WX_CARET_H_BASE_ diff --git a/include/wx/generic/caret.h b/include/wx/generic/caret.h new file mode 100644 index 0000000000..93df894ea6 --- /dev/null +++ b/include/wx/generic/caret.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: generic/caret.h +// Purpose: generic wxCaret class +// Author: Vadim Zeitlin (original code by Robert Roebling) +// Modified by: +// Created: 25.05.99 +// RCS-ID: $Id$ +// Copyright: (c) wxWindows team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#if 0 //def __GNUG__ + #pragma implementation "caret.h" +#endif + +#ifndef _WX_CARET_H_ +#define _WX_CARET_H_ + +#include "wx/timer.h" + +class wxCaret : public wxCaretBase +{ +public: + // ctors + // ----- + // default - use Create() + wxCaret() : m_timer(this) { InitGeneric(); } + // creates a block caret associated with the given window + wxCaret(wxWindowBase *window, int width, int height) + : wxCaretBase(window, width, height), m_timer(this) { InitGeneric(); } + wxCaret(wxWindowBase *window, const wxSize& size) + : wxCaretBase(window, size), m_timer(this) { InitGeneric(); } + + virtual ~wxCaret(); + + // implementation + // -------------- + + // blink the caret once + void Blink(); + +protected: + virtual void DoShow(); + virtual void DoHide(); + virtual void DoMove(); + + // draw the caret on the given DC + void DoDraw(wxDC *dc); + +private: + // GTK specific initialization + void InitGeneric(); + + class CaretTimer : public wxTimer + { + public: + CaretTimer(wxCaret *caret) { m_caret = caret; } + + virtual void Notify() { m_caret->Blink(); } + + private: + wxCaret *m_caret; + } m_timer; + + bool m_blinkedOut; // TRUE => caret hidden right now +}; + +#endif // _WX_CARET_H_ diff --git a/samples/caret/Makefile b/samples/caret/Makefile new file mode 100644 index 0000000000..bccce53f76 --- /dev/null +++ b/samples/caret/Makefile @@ -0,0 +1 @@ +include ../../setup/general/makeapp diff --git a/samples/caret/Makefile.in b/samples/caret/Makefile.in new file mode 100644 index 0000000000..5edaff3117 --- /dev/null +++ b/samples/caret/Makefile.in @@ -0,0 +1,24 @@ +# WXXT base directory +WXBASEDIR=@WXBASEDIR@ + +# set the OS type for compilation +OS=@OS@ +# compile a library only +RULE=bin + +# define library name +BIN_TARGET=caret +# define library sources +BIN_SRC=caret.cpp + +#define library objects +BIN_OBJ=caret.o + +# additional things needed to link +BIN_LINK= + +# additional things needed to compile +ADD_COMPILE= + +# include the definitions now +include ../../../template.mak diff --git a/samples/caret/caret.cpp b/samples/caret/caret.cpp new file mode 100644 index 0000000000..00df1d0b0d --- /dev/null +++ b/samples/caret/caret.cpp @@ -0,0 +1,390 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: caret.cpp +// Purpose: wxCaret sample +// Author: Robert Roebling +// Modified by: +// Created: 04/01/98 +// RCS-ID: $Id$ +// Copyright: (c) wxWindows team +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- +#ifdef __GNUG__ + #pragma implementation "caret.cpp" + #pragma interface "caret.cpp" +#endif + +// For compilers that support precompilation, includes "wx/wx.h". +#include + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +// for all others, include the necessary headers (this file is usually all you +// need because it includes almost all + + #include +#endif + +#include "wx/caret.h" + +// ---------------------------------------------------------------------------- +// ressources +// ---------------------------------------------------------------------------- +// the application icon +#if defined(__WXGTK__) || defined(__WXMOTIF__) + #include "mondrian.xpm" +#endif + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + +// Define a new application type, each program should derive a class from wxApp +class MyApp : public wxApp +{ +public: + // override base class virtuals + // ---------------------------- + + // this one is called on application startup and is a good place for the app + // initialization (doing it here and not in the ctor allows to have an error + // return: if OnInit() returns false, the application terminates) + virtual bool OnInit(); +}; + +// Define a new frame type: this is going to be our main frame +class MyFrame : public wxFrame +{ +public: + // ctor(s) + MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size); + + // event handlers (these functions should _not_ be virtual) + void OnQuit(wxCommandEvent& event); + void OnAbout(wxCommandEvent& event); + +private: + // any class wishing to process wxWindows events must use this macro + DECLARE_EVENT_TABLE() +}; + +// MyCanvas is a canvas on which you can type +class MyCanvas: public wxScrolledWindow +{ +public: + MyCanvas() { } + MyCanvas( wxWindow *parent ); + ~MyCanvas(); + + char& CharAt(int x, int y) { return *(m_text + x + m_xChars * y); } + + // caret movement + void Home() { m_xCaret = 0; } + void End() { m_xCaret = m_xChars - 1; } + void FirstLine() { m_yCaret = 0; } + void LastLine() { m_yCaret = m_yChars - 1; } + void PrevChar() { if ( !m_xCaret-- ) { End(); PrevLine(); } } + void NextChar() { if ( ++m_xCaret == m_xChars ) { Home(); NextLine(); } } + void PrevLine() { if ( !m_yCaret-- ) LastLine(); } + void NextLine() { if ( ++m_yCaret == m_yChars ) FirstLine(); } + + // event handlers + void OnPaint( wxPaintEvent &event ); + void OnSize( wxSizeEvent &event ); + void OnChar( wxKeyEvent &event ); + +private: + wxCaret m_caret; + wxFont m_font; + + // the margin around the text (looks nicer) + int m_xMargin, m_yMargin; + + // size (in pixels) of one character + long m_widthChar, m_heightChar; + + // position (in text coords) of the caret + int m_xCaret, m_yCaret; + + // the size (in text coords) of the window + int m_xChars, m_yChars; + + // the text + char *m_text; + + DECLARE_DYNAMIC_CLASS(MyCanvas) + DECLARE_EVENT_TABLE() +}; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// IDs for the controls and the menu commands +enum +{ + // menu items + Minimal_Quit = 1, + Minimal_About, + Minimal_Test1, + Minimal_Test2, + + // controls start here (the numbers are, of course, arbitrary) + Minimal_Text = 1000, +}; + +// ---------------------------------------------------------------------------- +// event tables and other macros for wxWindows +// ---------------------------------------------------------------------------- + +// the event tables connect the wxWindows events with the functions (event +// handlers) which process them. It can be also done at run-time, but for the +// simple menu events like this the static method is much simpler. +BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MENU(Minimal_Quit, MyFrame::OnQuit) + EVT_MENU(Minimal_About, MyFrame::OnAbout) +END_EVENT_TABLE() + +// Create a new application object: this macro will allow wxWindows to create +// the application object during program execution (it's better than using a +// static object for many reasons) and also declares the accessor function +// wxGetApp() which will return the reference of the right type (i.e. MyApp and +// not wxApp) +IMPLEMENT_APP(MyApp) + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// the application class +// ---------------------------------------------------------------------------- + +// `Main program' equivalent: the program execution "starts" here +bool MyApp::OnInit() +{ + // Create the main application window + MyFrame *frame = new MyFrame("Minimal wxWindows App", + wxPoint(50, 50), wxSize(450, 340)); + + // Show it and tell the application that it's our main window + // @@@ what does it do exactly, in fact? is it necessary here? + frame->Show(TRUE); + SetTopWindow(frame); + + // success: wxApp::OnRun() will be called which will enter the main message + // loop and the application will run. If we returned FALSE here, the + // application would exit immediately. + return TRUE; +} + +// ---------------------------------------------------------------------------- +// main frame +// ---------------------------------------------------------------------------- + +// frame constructor +MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size) + : wxFrame((wxFrame *)NULL, -1, title, pos, size) +{ + // set the frame icon + SetIcon(wxICON(mondrian)); + + // create a menu bar + wxMenu *menuFile = new wxMenu; + + menuFile->Append(Minimal_About, "&About...\tCtrl-A", "Show about dialog"); + menuFile->AppendSeparator(); + menuFile->Append(Minimal_Quit, "E&xit\tAlt-X", "Quit this program"); + + // now append the freshly created menu to the menu bar... + wxMenuBar *menuBar = new wxMenuBar; + menuBar->Append(menuFile, "&File"); + + // ... and attach this menu bar to the frame + SetMenuBar(menuBar); + + (void) new MyCanvas( this ); + + // create a status bar just for fun (by default with 1 pane only) + CreateStatusBar(2); + SetStatusText("Welcome to wxWindows!"); +} + + +// event handlers + +void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) +{ + // TRUE is to force the frame to close + Close(TRUE); +} + +void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) +{ + wxString msg; + msg.Printf( _T("This is the about dialog of minimal sample.\n") + _T("Welcome to %s") +#ifdef wxBETA_NUMBER + _T(" (beta %d)!") +#endif // wxBETA_NUMBER + , wxVERSION_STRING +#ifdef wxBETA_NUMBER + , wxBETA_NUMBER +#endif // wxBETA_NUMBER + ); + + wxMessageBox(msg, "About Minimal", wxOK | wxICON_INFORMATION, this); +} + + +// ---------------------------------------------------------------------------- +// MyCanvas +// ---------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(MyCanvas, wxScrolledWindow) + +BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) + EVT_PAINT(MyCanvas::OnPaint) + EVT_SIZE(MyCanvas::OnSize) + EVT_CHAR(MyCanvas::OnChar) +END_EVENT_TABLE() + +MyCanvas::MyCanvas( wxWindow *parent ) + : wxScrolledWindow( parent, -1, + wxDefaultPosition, wxDefaultSize, + wxSUNKEN_BORDER ) +{ + SetBackgroundColour(* wxWHITE); + + m_font = *wxNORMAL_FONT; + + wxClientDC dc(this); + dc.SetFont( m_font ); + m_heightChar = dc.GetCharHeight(); + m_widthChar = dc.GetCharWidth(); + + m_caret.Create( this, m_widthChar, m_heightChar ); + + m_xCaret = m_yCaret = + m_xChars = m_yChars = 0; + + m_xMargin = m_yMargin = 5; + m_caret.Move(m_xMargin, m_yMargin); + m_caret.Show(); + + m_text = (char *)NULL; +} + +MyCanvas::~MyCanvas() +{ + free(m_text); +} + +void MyCanvas::OnSize( wxSizeEvent &event ) +{ + m_xChars = (event.GetSize().x - 2*m_xMargin) / m_widthChar; + m_yChars = (event.GetSize().y - 2*m_yMargin) / m_heightChar; + if ( !m_xChars ) + m_xChars = 1; + if ( !m_yChars ) + m_yChars = 1; + + free(m_text); + m_text = (char *)calloc(m_xChars * m_yChars, sizeof(char)); + + wxString msg; + msg.Printf("Panel size is (%d, %d)", m_xChars, m_yChars); + + ((wxFrame *)GetParent())->SetStatusText(msg, 1); + + event.Skip(); +} + +void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) ) +{ + wxPaintDC dc( this ); + PrepareDC( dc ); + + dc.SetFont( m_font ); + + for ( int y = 0; y < m_yChars; y++ ) + { + wxString line; + + for ( int x = 0; x < m_xChars; x++ ) + { + char ch = CharAt(x, y); + if ( !ch ) + ch = ' '; + line += ch; + } + + dc.DrawText( line, m_xMargin, m_yMargin + y * m_heightChar ); + } +} + +void MyCanvas::OnChar( wxKeyEvent &event ) +{ + switch ( event.KeyCode() ) + { + case WXK_LEFT: + PrevChar(); + break; + + case WXK_RIGHT: + NextChar(); + break; + + case WXK_UP: + PrevLine(); + break; + + case WXK_DOWN: + NextLine(); + break; + + case WXK_HOME: + Home(); + break; + + case WXK_END: + End(); + break; + + case WXK_RETURN: + Home(); + NextLine(); + break; + + default: + if ( isprint(event.KeyCode()) ) + { + CharAt(m_xCaret, m_yCaret) = (char)event.KeyCode(); + NextChar(); + } + else + { + // don't refresh + return; + } + } + + wxLogStatus("Caret is at (%d, %d)", m_xCaret, m_yCaret); + + m_caret.Move(m_xMargin + m_xCaret * m_widthChar, + m_yMargin + m_yCaret * m_heightChar); + + Refresh(); +} + diff --git a/src/generic/caret.cpp b/src/generic/caret.cpp new file mode 100644 index 0000000000..59a9112c2c --- /dev/null +++ b/src/generic/caret.cpp @@ -0,0 +1,139 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: generic/caret.h +// Purpose: generic wxCaret class +// Author: Vadim Zeitlin (original code by Robert Roebling) +// Modified by: +// Created: 25.05.99 +// RCS-ID: $Id$ +// Copyright: (c) wxWindows team +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#if 0 //def __GNUG__ + #pragma implementation "caret.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif //WX_PRECOMP + +#include "wx/caret.h" + +// ---------------------------------------------------------------------------- +// global variables for this module +// ---------------------------------------------------------------------------- + +// the blink time (common to all carets for MSW compatibility) +static int gs_blinkTime = 500; // in milliseconds + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxCaret static functions and data +// ---------------------------------------------------------------------------- + + +int wxCaretBase::GetBlinkTime() +{ + return gs_blinkTime; +} + +void wxCaretBase::SetBlinkTime(int milliseconds) +{ + gs_blinkTime = milliseconds; +} + +// ---------------------------------------------------------------------------- +// initialization and destruction +// ---------------------------------------------------------------------------- + +void wxCaret::InitGeneric() +{ +} + +wxCaret::~wxCaret() +{ + if ( IsVisible() ) + { + // stop blinking + m_timer.Stop(); + } +} + +// ---------------------------------------------------------------------------- +// showing/hiding/moving the caret (base class interface) +// ---------------------------------------------------------------------------- + +void wxCaret::DoShow() +{ + m_timer.Start(GetBlinkTime()); + + m_blinkedOut = TRUE; + Blink(); +} + +void wxCaret::DoHide() +{ + m_timer.Stop(); + + if ( !m_blinkedOut ) + { + Blink(); + } +} + +void wxCaret::DoMove() +{ + if ( IsVisible() && !m_blinkedOut ) + { + Blink(); + } + //else: will be shown at the correct location next time it blinks +} + +// ---------------------------------------------------------------------------- +// drawing the caret +// ---------------------------------------------------------------------------- + +void wxCaret::Blink() +{ + m_blinkedOut = !m_blinkedOut; + + wxClientDC dc(GetWindow()); + if ( !m_blinkedOut ) + { + DoDraw(&dc); + } + else + { + // FIXME can't be less efficient than this... (+1 needed!) + wxRect rect(m_x, m_y, m_width + 1, m_height + 1); + GetWindow()->Refresh(FALSE, &rect); + } +} + +void wxCaret::DoDraw(wxDC *dc) +{ + dc->SetPen( *wxBLACK_PEN ); + dc->DrawLine( m_x, m_y, m_x+m_width, m_y ); + dc->DrawLine( m_x, m_y+m_height, m_x+m_width, m_y+m_height ); + dc->DrawLine( m_x+(m_width/2), m_y, m_x+(m_width/2), m_y+m_height ); +// dc->DrawLine( m_x+(m_width/2)+1, m_y, m_x+(m_width/2)+1, m_y+m_height ); +}