]> git.lyx.org Git - features.git/commitdiff
make WorkArea a pure interface, move all implementation to GuiWorkArea
authorAndré Pönitz <poenitz@gmx.net>
Mon, 12 Nov 2007 22:15:51 +0000 (22:15 +0000)
committerAndré Pönitz <poenitz@gmx.net>
Mon, 12 Nov 2007 22:15:51 +0000 (22:15 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@21557 a592a061-630c-0410-9148-cb99ea01b6c8

src/frontends/KeyModifier.h
src/frontends/Makefile.am
src/frontends/WorkArea.cpp [deleted file]
src/frontends/WorkArea.h
src/frontends/WorkAreaManager.cpp
src/frontends/WorkAreaManager.h
src/frontends/qt4/GuiView.cpp
src/frontends/qt4/GuiView.h
src/frontends/qt4/GuiWorkArea.cpp
src/frontends/qt4/GuiWorkArea.h

index db5beffd431f3b17129b0a51f18a29fd93568aaf..7c8035f91ff784e85141573d2f32d785c9d08d43 100644 (file)
@@ -1,6 +1,6 @@
 // -*- C++ -*-
 /**
- * \file key_state.h
+ * \file KeyModifier.h
  * This file is part of LyX, the document processor.
  * Licence details can be found in the file COPYING.
  *
@@ -19,10 +19,10 @@ namespace lyx {
 /// modifier key states
 
 enum KeyModifier {
-       NoModifier  = 0, //< no modifiers held
+       NoModifier       = 0, //< no modifiers held
        ControlModifier  = 1, //< control button held
-       AltModifier   = 2, //< alt/meta key held
-       ShiftModifier = 4  //< shift key held
+       AltModifier      = 2, //< alt/meta key held
+       ShiftModifier    =  4  //< shift key held
 };
 
 
@@ -42,4 +42,4 @@ inline void operator|=(KeyModifier & s1, KeyModifier s2)
 
 } // namespace lyx
 
-#endif // KEY_STATE_H
+#endif // KEYMODIFIER_H
index 9cacd469956c4f2a03771b8e796b32aee9836678..eabbacbe086afe962a8649e6cf4ef641fe863163 100644 (file)
@@ -34,7 +34,6 @@ liblyxfrontends_la_SOURCES = \
        Clipboard.h \
        Gui.h \
        Selection.h \
-       WorkArea.cpp \
        WorkArea.h \
        WorkAreaManager.cpp \
        WorkAreaManager.h \
diff --git a/src/frontends/WorkArea.cpp b/src/frontends/WorkArea.cpp
deleted file mode 100644 (file)
index 849cade..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/**
- * \file WorkArea.cpp
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author John Levon
- * \author Abdelrazak Younes
- *
- * Full author contact details are available in file CREDITS.
- *
- * Splash screen code added by Angus Leeming
- */
-
-#include <config.h>
-
-#include "frontends/WorkArea.h"
-
-#include "frontends/Application.h"
-#include "frontends/Dialogs.h"
-#include "frontends/FontMetrics.h"
-#include "frontends/LyXView.h"
-#include "frontends/WorkAreaManager.h"
-
-#include "BufferView.h"
-#include "Buffer.h"
-#include "BufferParams.h"
-#include "CoordCache.h"
-#include "Cursor.h"
-#include "debug.h"
-#include "Font.h"
-#include "FuncRequest.h"
-#include "KeySymbol.h"
-#include "Language.h"
-#include "LyXFunc.h"
-#include "LyXRC.h"
-#include "MetricsInfo.h"
-
-#include "gettext.h"
-#include "support/FileName.h"
-#include "support/filetools.h"
-#include "support/ForkedcallsController.h"
-
-#include <boost/noncopyable.hpp>
-#include <boost/bind.hpp>
-#include <boost/current_function.hpp>
-
-using std::endl;
-using std::min;
-using std::max;
-using std::string;
-
-
-namespace {
-
-// All the below connection objects are needed because of a bug in some
-// versions of GCC (<=2.96 are on the suspects list.) By having and assigning
-// to these connections we avoid a segfault upon startup, and also at exit.
-// (Lgb)
-
-boost::signals::connection timecon;
-
-} // anon namespace
-
-namespace lyx {
-
-using support::ForkedcallsController;
-using support::makeDisplayPath;
-using support::onlyFilename;
-
-namespace frontend {
-
-WorkArea::WorkArea(Buffer & buffer, LyXView & lv)
-       : buffer_view_(new BufferView(buffer)), lyx_view_(&lv),
-       cursor_visible_(false), cursor_timeout_(400)
-{
-       buffer.workAreaManager().add(this);
-       // Setup the signals
-       timecon = cursor_timeout_.timeout
-               .connect(boost::bind(&WorkArea::toggleCursor, this));
-
-       cursor_timeout_.start();
-}
-
-
-WorkArea::~WorkArea()
-{
-       buffer_view_->buffer().workAreaManager().remove(this);
-       delete buffer_view_;
-}
-
-
-void WorkArea::close()
-{
-       lyx_view_->removeWorkArea(this);
-}
-
-//void WorkArea::setLyXView(LyXView * lyx_view)
-//{
-//     lyx_view_ = lyx_view;
-//}
-
-
-BufferView & WorkArea::bufferView()
-{
-       return *buffer_view_;
-}
-
-
-BufferView const & WorkArea::bufferView() const
-{
-       return *buffer_view_;
-}
-
-
-void WorkArea::stopBlinkingCursor()
-{
-       cursor_timeout_.stop();
-       hideCursor();
-}
-
-
-void WorkArea::startBlinkingCursor()
-{
-       showCursor();
-       cursor_timeout_.restart();
-}
-
-
-void WorkArea::redraw()
-{
-       if (!isVisible())
-               // No need to redraw in this case.
-               return;
-
-       // No need to do anything if this is the current view. The BufferView
-       // metrics are already up to date.
-       if (lyx_view_ != theApp()->currentView()) {
-               // FIXME: it would be nice to optimize for the off-screen case.
-               buffer_view_->updateMetrics();
-               buffer_view_->cursor().fixIfBroken();
-       }
-
-       updateScrollbar();
-
-       // update cursor position, because otherwise it has to wait until
-       // the blinking interval is over
-       if (cursor_visible_) {
-               hideCursor();
-               showCursor();
-       }
-       
-       ViewMetricsInfo const & vi = buffer_view_->viewMetricsInfo();
-
-       LYXERR(Debug::WORKAREA) << "WorkArea::redraw screen" << endl;
-
-       int const ymin = std::max(vi.y1, 0);
-       int const ymax = vi.p2 < vi.size - 1 ? vi.y2 : height();
-
-       expose(0, ymin, width(), ymax - ymin);
-
-       //LYXERR(Debug::WORKAREA)
-       //<< "  ymin = " << ymin << "  width() = " << width()
-//             << "  ymax-ymin = " << ymax-ymin << std::endl;
-
-       if (lyxerr.debugging(Debug::WORKAREA))
-               buffer_view_->coordCache().dump();
-}
-
-
-void WorkArea::processKeySym(KeySymbol const & key, KeyModifier mod)
-{
-       // In order to avoid bad surprise in the middle of an operation, we better stop
-       // the blinking cursor.
-       stopBlinkingCursor();
-
-       theLyXFunc().setLyXView(lyx_view_);
-       theLyXFunc().processKeySym(key, mod);
-}
-
-
-void WorkArea::dispatch(FuncRequest const & cmd0, KeyModifier mod)
-{
-       // Handle drag&drop
-       if (cmd0.action == LFUN_FILE_OPEN) {
-               lyx_view_->dispatch(cmd0);
-               return;
-       }
-
-       theLyXFunc().setLyXView(lyx_view_);
-
-       FuncRequest cmd;
-
-       if (cmd0.action == LFUN_MOUSE_PRESS) {
-               if (mod == ShiftModifier)
-                       cmd = FuncRequest(cmd0, "region-select");
-               else if (mod == ControlModifier)
-                       cmd = FuncRequest(cmd0, "paragraph-select");
-               else
-                       cmd = cmd0;
-       }
-       else
-               cmd = cmd0;
-
-       // In order to avoid bad surprise in the middle of an operation, we better stop
-       // the blinking cursor.
-       if (!(cmd.action == LFUN_MOUSE_MOTION
-               && cmd.button() == mouse_button::none))
-               stopBlinkingCursor();
-
-       buffer_view_->mouseEventDispatch(cmd);
-
-       // Skip these when selecting
-       if (cmd.action != LFUN_MOUSE_MOTION) {
-               lyx_view_->updateLayoutChoice(false);
-               lyx_view_->updateToolbars();
-       }
-
-       // GUI tweaks except with mouse motion with no button pressed.
-       if (!(cmd.action == LFUN_MOUSE_MOTION
-               && cmd.button() == mouse_button::none)) {
-               // Slight hack: this is only called currently when we
-               // clicked somewhere, so we force through the display
-               // of the new status here.
-               lyx_view_->clearMessage();
-
-               // Show the cursor immediately after any operation.
-               startBlinkingCursor();
-       }
-}
-
-
-void WorkArea::resizeBufferView()
-{
-       // WARNING: Please don't put any code that will trigger a repaint here!
-       // We are already inside a paint event.
-       lyx_view_->setBusy(true);
-       buffer_view_->resize(width(), height());
-       lyx_view_->updateLayoutChoice(false);
-       lyx_view_->setBusy(false);
-}
-
-
-void WorkArea::updateScrollbar()
-{
-       buffer_view_->updateScrollbar();
-       ScrollbarParameters const & scroll_ = buffer_view_->scrollbarParameters();
-       setScrollbarParams(scroll_.height, scroll_.position,
-               scroll_.lineScrollHeight);
-}
-
-
-void WorkArea::showCursor()
-{
-       if (cursor_visible_)
-               return;
-
-       CursorShape shape = BAR_SHAPE;
-
-       Font const & realfont = buffer_view_->cursor().real_current_font;
-       BufferParams const & bp = buffer_view_->buffer().params();
-       bool const samelang = realfont.language() == bp.language;
-       bool const isrtl = realfont.isVisibleRightToLeft();
-
-       if (!samelang || isrtl != bp.language->rightToLeft()) {
-               shape = L_SHAPE;
-               if (isrtl)
-                       shape = REVERSED_L_SHAPE;
-       }
-
-       // The ERT language hack needs fixing up
-       if (realfont.language() == latex_language)
-               shape = BAR_SHAPE;
-
-       Font const font = buffer_view_->cursor().getFont();
-       FontMetrics const & fm = theFontMetrics(font);
-       int const asc = fm.maxAscent();
-       int const des = fm.maxDescent();
-       int h = asc + des;
-       int x = 0;
-       int y = 0;
-       buffer_view_->cursor().getPos(x, y);
-       y -= asc;
-
-       // if it doesn't touch the screen, don't try to show it
-       if (y + h < 0 || y >= height())
-               return;
-
-       cursor_visible_ = true;
-       showCursor(x, y, h, shape);
-}
-
-
-void WorkArea::hideCursor()
-{
-       if (!cursor_visible_)
-               return;
-
-       cursor_visible_ = false;
-       removeCursor();
-}
-
-
-void WorkArea::toggleCursor()
-{
-       if (cursor_visible_)
-               hideCursor();
-       else
-               showCursor();
-
-       // Use this opportunity to deal with any child processes that
-       // have finished but are waiting to communicate this fact
-       // to the rest of LyX.
-       ForkedcallsController & fcc = ForkedcallsController::get();
-       fcc.handleCompletedProcesses();
-
-       cursor_timeout_.restart();
-}
-
-void WorkArea::updateWindowTitle()
-{
-       docstring maximize_title;
-       docstring minimize_title;
-
-       Buffer & buf = buffer_view_->buffer();
-       string const cur_title = buf.absFileName();
-       if (!cur_title.empty()) {
-               maximize_title = makeDisplayPath(cur_title, 30);
-               minimize_title = from_utf8(onlyFilename(cur_title));
-               if (!buf.isClean()) {
-                       maximize_title += _(" (changed)");
-                       minimize_title += char_type('*');
-               }
-               if (buf.isReadonly())
-                       maximize_title += _(" (read only)");
-       }
-
-       setWindowTitle(maximize_title, minimize_title);
-}
-
-
-void WorkArea::setReadOnly(bool)
-{
-       updateWindowTitle();
-       if (this == lyx_view_->currentWorkArea())
-               lyx_view_->getDialogs().updateBufferDependent(false);
-}
-
-} // namespace frontend
-} // namespace lyx
index 306b655532b6bad3b91045067c4447bdf876ccad..e8508d06f006279bc905c36dd51eaa44e86bcec5 100644 (file)
 #define BASE_WORKAREA_H
 
 #include "frontends/KeyModifier.h"
-#include "frontends/Delegates.h"
-
-#include "support/Timeout.h"
-#include "support/docstring.h"
-
-#undef CursorShape
 
 namespace lyx {
 
-class Buffer;
 class BufferView;
-class FuncRequest;
 class KeySymbol;
 
 namespace frontend {
@@ -34,16 +26,6 @@ namespace frontend {
 class LyXView;
 class Painter;
 
-/// types of cursor in work area
-enum CursorShape {
-       /// normal I-beam
-       BAR_SHAPE,
-       /// L-shape for locked insets of a different language
-       L_SHAPE,
-       /// reverse L-shape for RTL text
-       REVERSED_L_SHAPE
-};
-
 /**
  * The work area class represents the widget that provides the
  * view onto a document. It is owned by the BufferView, and
@@ -55,22 +37,22 @@ class WorkArea
 {
 public:
        ///
-       WorkArea(Buffer & buffer, LyXView & lv);
+       WorkArea() {}
 
        virtual ~WorkArea();
 
        ///
-       void setLyXView(LyXView & lv) { lyx_view_ = &lv; }
+       virtual void setLyXView(LyXView & lv) = 0;
 
        ///
-       BufferView & bufferView();
+       virtual BufferView & bufferView() = 0;
        ///
-       BufferView const & bufferView() const;
+       virtual BufferView const & bufferView() const = 0;
 
-       /// \return true if has the keyboard input focus.
+       /// return true if has the keyboard input focus.
        virtual bool hasFocus() const = 0;
 
-       /// \return true if has this WorkArea is visible.
+       /// return true if has this WorkArea is visible.
        virtual bool isVisible() const = 0;
 
        /// return the width of the work area in pixels
@@ -91,65 +73,23 @@ public:
        virtual void scheduleRedraw() = 0;
 
        /// redraw the screen, without using existing pixmap
-       virtual void redraw();
+       virtual void redraw() = 0;
        ///
-       void stopBlinkingCursor();
-       void startBlinkingCursor();
+       virtual void stopBlinkingCursor() = 0;
+       virtual void startBlinkingCursor() = 0;
 
        /// Process Key pressed event.
        /// This needs to be public because it is accessed externally by GuiView.
-       void processKeySym(KeySymbol const & key, KeyModifier mod);
+       virtual void processKeySym(KeySymbol const & key, KeyModifier mod) = 0;
 
        /// close this work area.
        /// Slot for Buffer::closing signal.
-       void close();
-
+       virtual void close() = 0;
        /// This function is called when the buffer readonly status change.
-       virtual void setReadOnly(bool);
+       virtual void setReadOnly(bool) = 0;
 
        /// Update window titles of all users.
-       virtual void updateWindowTitle();
-
-protected:
-       /// cause the display of the given area of the work area
-       virtual void expose(int x, int y, int w, int h) = 0;
-
-       /// set title of window.
-       /**
-        * @param t main window title
-        * @param it iconified (short) title
-        */
-       virtual void setWindowTitle(docstring const & t, docstring const & it) = 0;
-
-       ///
-       void dispatch(FuncRequest const & cmd0, KeyModifier = NoModifier);
-
-       ///
-       void resizeBufferView();
-       /// hide the visible cursor, if it is visible
-       void hideCursor();
-       /// show the cursor if it is not visible
-       void showCursor();
-       /// toggle the cursor's visibility
-       void toggleCursor();
-       /// hide the cursor
-       virtual void removeCursor() = 0;
-       /// paint the cursor and store the background
-       virtual void showCursor(int x, int y, int h, CursorShape shape) = 0;
-       ///
-       void updateScrollbar();
-
-       ///
-       BufferView * buffer_view_;
-       ///
-       LyXView * lyx_view_;
-
-private:
-       /// is the cursor currently displayed
-       bool cursor_visible_;
-
-       ///
-       Timeout cursor_timeout_;
+       virtual void updateWindowTitle() = 0;
 };
 
 } // namespace frontend
index e3c8d3e2a774a307994f4cb935dcac7ff1567ab3..b0eaaac6b1270f539671d005ba6cd5550aceee69 100644 (file)
 
 #include <config.h>
 
-#include "WorkArea.h"
-
 #include "WorkAreaManager.h"
 
-using std::list;
-
-namespace lyx {
+#include "WorkArea.h"
 
-extern bool quitting;
 
+namespace lyx {
 namespace frontend {
 
 void WorkAreaManager::add(WorkArea * wa)
@@ -37,11 +33,8 @@ void WorkAreaManager::remove(WorkArea * wa)
 
 void WorkAreaManager::redrawAll()
 {
-       for (list<WorkArea *>::iterator it = work_areas_.begin();
-               it != work_areas_.end(); ) {
+       for (iterator it = work_areas_.begin(); it != work_areas_.end(); ++it)
                (*it)->redraw();
-               ++it;
-       }
 }
 
 
@@ -55,21 +48,15 @@ void WorkAreaManager::closeAll()
 
 void WorkAreaManager::setReadOnly(bool on)
 {
-       for (list<WorkArea *>::iterator it = work_areas_.begin();
-               it != work_areas_.end(); ) {
+       for (iterator it = work_areas_.begin(); it != work_areas_.end(); ++it)
                (*it)->setReadOnly(on);
-               ++it;
-       }
 }
 
 
 void WorkAreaManager::updateTitles()
 {
-       for (list<WorkArea *>::iterator it = work_areas_.begin();
-               it != work_areas_.end(); ) {
+       for (iterator it = work_areas_.begin(); it != work_areas_.end(); ++it)
                (*it)->updateWindowTitle();
-               ++it;
-       }
 }
 
 } // namespace frontend
index 00f7de53fe3eec9eb63678a395f617dcad161192..7d389c67034b82e5993887a9e139a06d9bf117ba 100644 (file)
@@ -28,27 +28,24 @@ class WorkArea;
 class WorkAreaManager
 {
 public:
+       ///
        WorkAreaManager() {}
-
        ///
        void add(WorkArea * wa);
-
        ///
        void remove(WorkArea * wa);
-
        ///
        void redrawAll();
-
        ///
        void closeAll();
-
        /// This function is called when the buffer readonly status change.
-       virtual void setReadOnly(bool);
-
+       void setReadOnly(bool);
        /// Update window titles of all users.
-       virtual void updateTitles();
+       void updateTitles();
 
 private:
+       typedef std::list<WorkArea *>::iterator iterator;
+       ///
        std::list<WorkArea *> work_areas_;
 };
 
index c79fc1a319a225644df4fa58c5b4ba47ea411453..9fed4ddbc2931ec8d1bb192ed2adb0859005bb21 100644 (file)
@@ -121,7 +121,7 @@ private:
        QPixmap * splash_;
 };
 
-};
+} // namespace anon
 
 
 struct GuiView::GuiViewPrivate
index 78a7859a242bc400ba8c9742d384d3d2a5b4a587..b5b44668589efd55ac462880cf38363cd74be384 100644 (file)
@@ -140,14 +140,20 @@ private:
        /// in order to catch Tab key press.
        bool event(QEvent * e);
        bool focusNextPrevChild(bool);
+       ///
+       QRect updateFloatingGeometry();
+
+private:
+       ///
+       struct GuiViewPrivate;
+       GuiViewPrivate & d;
 
+       ///
        QTimer statusbar_timer_;
 
        /// are we quitting by the menu?
        bool quitting_by_menu_;
 
-       ///
-       QRect updateFloatingGeometry();
        ///
        QRect floatingGeometry_;
 
@@ -161,9 +167,6 @@ private:
        };
 
        ToolbarSize toolbarSize_;
-
-       struct GuiViewPrivate;
-       GuiViewPrivate& d;
 };
 
 
index e6deea60bd0a047427941988375ed5f36a27b701..06e1d824cf5f37d00d9855e93cf7156dd6949553 100644 (file)
 
 #include "GuiWorkArea.h"
 
-#include "GuiApplication.h"
-#include "GuiPainter.h"
-#include "GuiKeySymbol.h"
-#include "qt_helpers.h"
-
-#include "frontends/LyXView.h"
-
 #include "Buffer.h"
+#include "BufferParams.h"
 #include "BufferView.h"
+#include "CoordCache.h"
 #include "Cursor.h"
 #include "debug.h"
+#include "Font.h"
 #include "FuncRequest.h"
+#include "gettext.h"
+#include "GuiApplication.h"
+#include "GuiKeySymbol.h"
+#include "GuiPainter.h"
+#include "KeySymbol.h"
+#include "Language.h"
 #include "LyXFunc.h"
 #include "LyXRC.h"
+#include "MetricsInfo.h"
+#include "qt_helpers.h"
 #include "version.h"
 
 #include "graphics/GraphicsImage.h"
 #include "graphics/GraphicsLoader.h"
 
+#include "support/FileName.h"
+#include "support/ForkedcallsController.h"
+
+#include "frontends/Application.h"
+#include "frontends/Dialogs.h"  // only used in setReadOnly
+#include "frontends/FontMetrics.h"
+#include "frontends/LyXView.h"
+#include "frontends/WorkAreaManager.h"
+
 #include <QInputContext>
 #include <QLayout>
 #include <QMainWindow>
@@ -42,8 +55,8 @@
 #include <QTabBar>
 #include <QTimer>
 
-#include <boost/current_function.hpp>
 #include <boost/bind.hpp>
+#include <boost/current_function.hpp>
 
 #ifdef Q_WS_X11
 #include <QX11Info>
@@ -60,11 +73,15 @@ int const CursorWidth = 1;
 #undef NoModifier 
 
 using std::endl;
+using std::min;
+using std::max;
 using std::string;
 
 namespace lyx {
 
 using support::FileName;
+using support::ForkedcallsController;
+
 
 /// return the LyX mouse button state from Qt's
 static mouse_button::state q_button_state(Qt::MouseButton button)
@@ -174,10 +191,31 @@ SyntheticMouseEvent::SyntheticMouseEvent()
 {}
 
 
-GuiWorkArea::GuiWorkArea(Buffer & buf, LyXView & lv)
-       : WorkArea(buf, lv), need_resize_(false), schedule_redraw_(false),
-         preedit_lines_(1)
+
+// All the below connection objects are needed because of a bug in some
+// versions of GCC (<=2.96 are on the suspects list.) By having and assigning
+// to these connections we avoid a segfault upon startup, and also at exit.
+// (Lgb)
+
+static boost::signals::connection timecon;
+
+// HACK: FIXME
+WorkArea::~WorkArea() {}
+
+
+GuiWorkArea::GuiWorkArea(Buffer & buffer, LyXView & lv)
+       : buffer_view_(new BufferView(buffer)), lyx_view_(&lv),
+         cursor_visible_(false), cursor_timeout_(400),
+    need_resize_(false), schedule_redraw_(false),
+               preedit_lines_(1)
 {
+       buffer.workAreaManager().add(this);
+       // Setup the signals
+       timecon = cursor_timeout_.timeout
+               .connect(boost::bind(&GuiWorkArea::toggleCursor, this));
+
+       cursor_timeout_.start();
+
        screen_ = QPixmap(viewport()->width(), viewport()->height());
        cursor_ = new frontend::CursorWidget();
        cursor_->hide();
@@ -200,7 +238,7 @@ GuiWorkArea::GuiWorkArea(Buffer & buf, LyXView & lv)
 
        synthetic_mouse_event_.timeout.timeout.connect(
                boost::bind(&GuiWorkArea::generateSyntheticMouseEvent,
-                           this));
+                                       this));
 
        // Initialize the vertical Scroll Bar
        QObject::connect(verticalScrollBar(), SIGNAL(actionTriggered(int)),
@@ -225,6 +263,237 @@ GuiWorkArea::GuiWorkArea(Buffer & buf, LyXView & lv)
 }
 
 
+
+GuiWorkArea::~GuiWorkArea()
+{
+       buffer_view_->buffer().workAreaManager().remove(this);
+       delete buffer_view_;
+}
+
+
+void GuiWorkArea::close()
+{
+       lyx_view_->removeWorkArea(this);
+}
+
+
+BufferView & GuiWorkArea::bufferView()
+{
+       return *buffer_view_;
+}
+
+
+BufferView const & GuiWorkArea::bufferView() const
+{
+       return *buffer_view_;
+}
+
+
+void GuiWorkArea::stopBlinkingCursor()
+{
+       cursor_timeout_.stop();
+       hideCursor();
+}
+
+
+void GuiWorkArea::startBlinkingCursor()
+{
+       showCursor();
+       cursor_timeout_.restart();
+}
+
+
+void GuiWorkArea::redraw()
+{
+       if (!isVisible())
+               // No need to redraw in this case.
+               return;
+
+       // No need to do anything if this is the current view. The BufferView
+       // metrics are already up to date.
+       if (lyx_view_ != theApp()->currentView()) {
+               // FIXME: it would be nice to optimize for the off-screen case.
+               buffer_view_->updateMetrics();
+               buffer_view_->cursor().fixIfBroken();
+       }
+
+       updateScrollbar();
+
+       // update cursor position, because otherwise it has to wait until
+       // the blinking interval is over
+       if (cursor_visible_) {
+               hideCursor();
+               showCursor();
+       }
+       
+       ViewMetricsInfo const & vi = buffer_view_->viewMetricsInfo();
+
+       LYXERR(Debug::WORKAREA) << "WorkArea::redraw screen" << endl;
+
+       int const ymin = std::max(vi.y1, 0);
+       int const ymax = vi.p2 < vi.size - 1 ? vi.y2 : height();
+
+       expose(0, ymin, width(), ymax - ymin);
+
+       //LYXERR(Debug::WORKAREA)
+       //<< "  ymin = " << ymin << "  width() = " << width()
+//             << "  ymax-ymin = " << ymax-ymin << std::endl;
+
+       if (lyxerr.debugging(Debug::WORKAREA))
+               buffer_view_->coordCache().dump();
+}
+
+
+void GuiWorkArea::processKeySym(KeySymbol const & key, KeyModifier mod)
+{
+       // In order to avoid bad surprise in the middle of an operation,
+       // we better stop the blinking cursor.
+       stopBlinkingCursor();
+
+       theLyXFunc().setLyXView(lyx_view_);
+       theLyXFunc().processKeySym(key, mod);
+}
+
+
+void GuiWorkArea::dispatch(FuncRequest const & cmd0, KeyModifier mod)
+{
+       // Handle drag&drop
+       if (cmd0.action == LFUN_FILE_OPEN) {
+               lyx_view_->dispatch(cmd0);
+               return;
+       }
+
+       theLyXFunc().setLyXView(lyx_view_);
+
+       FuncRequest cmd;
+
+       if (cmd0.action == LFUN_MOUSE_PRESS) {
+               if (mod == ShiftModifier)
+                       cmd = FuncRequest(cmd0, "region-select");
+               else if (mod == ControlModifier)
+                       cmd = FuncRequest(cmd0, "paragraph-select");
+               else
+                       cmd = cmd0;
+       }
+       else
+               cmd = cmd0;
+
+       // In order to avoid bad surprise in the middle of an operation, we better stop
+       // the blinking cursor.
+       if (!(cmd.action == LFUN_MOUSE_MOTION
+               && cmd.button() == mouse_button::none))
+               stopBlinkingCursor();
+
+       buffer_view_->mouseEventDispatch(cmd);
+
+       // Skip these when selecting
+       if (cmd.action != LFUN_MOUSE_MOTION) {
+               lyx_view_->updateLayoutChoice(false);
+               lyx_view_->updateToolbars();
+       }
+
+       // GUI tweaks except with mouse motion with no button pressed.
+       if (!(cmd.action == LFUN_MOUSE_MOTION
+               && cmd.button() == mouse_button::none)) {
+               // Slight hack: this is only called currently when we
+               // clicked somewhere, so we force through the display
+               // of the new status here.
+               lyx_view_->clearMessage();
+
+               // Show the cursor immediately after any operation.
+               startBlinkingCursor();
+       }
+}
+
+
+void GuiWorkArea::resizeBufferView()
+{
+       // WARNING: Please don't put any code that will trigger a repaint here!
+       // We are already inside a paint event.
+       lyx_view_->setBusy(true);
+       buffer_view_->resize(width(), height());
+       lyx_view_->updateLayoutChoice(false);
+       lyx_view_->setBusy(false);
+}
+
+
+void GuiWorkArea::updateScrollbar()
+{
+       buffer_view_->updateScrollbar();
+       ScrollbarParameters const & scroll_ = buffer_view_->scrollbarParameters();
+       setScrollbarParams(scroll_.height, scroll_.position,
+               scroll_.lineScrollHeight);
+}
+
+
+void GuiWorkArea::showCursor()
+{
+       if (cursor_visible_)
+               return;
+
+       CursorShape shape = BAR_SHAPE;
+
+       Font const & realfont = buffer_view_->cursor().real_current_font;
+       BufferParams const & bp = buffer_view_->buffer().params();
+       bool const samelang = realfont.language() == bp.language;
+       bool const isrtl = realfont.isVisibleRightToLeft();
+
+       if (!samelang || isrtl != bp.language->rightToLeft()) {
+               shape = L_SHAPE;
+               if (isrtl)
+                       shape = REVERSED_L_SHAPE;
+       }
+
+       // The ERT language hack needs fixing up
+       if (realfont.language() == latex_language)
+               shape = BAR_SHAPE;
+
+       Font const font = buffer_view_->cursor().getFont();
+       FontMetrics const & fm = theFontMetrics(font);
+       int const asc = fm.maxAscent();
+       int const des = fm.maxDescent();
+       int h = asc + des;
+       int x = 0;
+       int y = 0;
+       buffer_view_->cursor().getPos(x, y);
+       y -= asc;
+
+       // if it doesn't touch the screen, don't try to show it
+       if (y + h < 0 || y >= height())
+               return;
+
+       cursor_visible_ = true;
+       showCursor(x, y, h, shape);
+}
+
+
+void GuiWorkArea::hideCursor()
+{
+       if (!cursor_visible_)
+               return;
+
+       cursor_visible_ = false;
+       removeCursor();
+}
+
+
+void GuiWorkArea::toggleCursor()
+{
+       if (cursor_visible_)
+               hideCursor();
+       else
+               showCursor();
+
+       // Use this opportunity to deal with any child processes that
+       // have finished but are waiting to communicate this fact
+       // to the rest of LyX.
+       ForkedcallsController & fcc = ForkedcallsController::get();
+       fcc.handleCompletedProcesses();
+
+       cursor_timeout_.restart();
+}
+
+
 void GuiWorkArea::setScrollbarParams(int h, int scroll_pos, int scroll_line_step)
 {
        if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOn)
@@ -441,7 +710,7 @@ void GuiWorkArea::doubleClickTimeout()
 
 void GuiWorkArea::mouseDoubleClickEvent(QMouseEvent * ev)
 {
-       dc_event_ = double_click(ev);
+       dc_event_ = DoubleClick(ev);
        QTimer::singleShot(QApplication::doubleClickInterval(), this,
                           SLOT(doubleClickTimeout()));
        FuncRequest cmd(LFUN_MOUSE_DOUBLE,
@@ -479,8 +748,8 @@ void GuiWorkArea::paintEvent(QPaintEvent * ev)
                screen_ = QPixmap(viewport()->width(), viewport()->height());
                resizeBufferView();
                updateScreen();
-               WorkArea::hideCursor();
-               WorkArea::showCursor();
+               hideCursor();
+               showCursor();
                need_resize_ = false;
        }
 
@@ -704,18 +973,51 @@ QVariant GuiWorkArea::inputMethodQuery(Qt::InputMethodQuery query) const
 }
 
 
+void GuiWorkArea::updateWindowTitle()
+{
+       docstring maximize_title;
+       docstring minimize_title;
+
+       Buffer & buf = buffer_view_->buffer();
+       FileName const fileName = buf.fileName();
+       if (!fileName.empty()) {
+               maximize_title = fileName.displayName(30);
+               minimize_title = from_utf8(fileName.onlyFileName());
+               if (!buf.isClean()) {
+                       maximize_title += _(" (changed)");
+                       minimize_title += char_type('*');
+               }
+               if (buf.isReadonly())
+                       maximize_title += _(" (read only)");
+       }
+
+       setWindowTitle(maximize_title, minimize_title);
+}
+
+
+void GuiWorkArea::setReadOnly(bool)
+{
+       updateWindowTitle();
+       if (this == lyx_view_->currentWorkArea())
+               lyx_view_->getDialogs().updateBufferDependent(false);
+}
+
+
 ////////////////////////////////////////////////////////////////////
 //
 // TabWorkArea 
 //
 ////////////////////////////////////////////////////////////////////
 
-TabWorkArea::TabWorkArea(QWidget * parent): QTabWidget(parent)
+TabWorkArea::TabWorkArea(QWidget * parent) : QTabWidget(parent)
 {
        QPalette pal = palette();
-       pal.setColor(QPalette::Active, QPalette::Button, pal.color(QPalette::Active, QPalette::Window));
-       pal.setColor(QPalette::Disabled, QPalette::Button, pal.color(QPalette::Disabled, QPalette::Window));
-       pal.setColor(QPalette::Inactive, QPalette::Button, pal.color(QPalette::Inactive, QPalette::Window));
+       pal.setColor(QPalette::Active, QPalette::Button,
+               pal.color(QPalette::Active, QPalette::Window));
+       pal.setColor(QPalette::Disabled, QPalette::Button,
+               pal.color(QPalette::Disabled, QPalette::Window));
+       pal.setColor(QPalette::Inactive, QPalette::Button,
+               pal.color(QPalette::Inactive, QPalette::Window));
 
        QToolButton * closeTabButton = new QToolButton(this);
     closeTabButton->setPalette(pal);
index ae1f752601a392cc03d1c9d4a0643e72c594d187..54d033b43cc7f9983c844a24f716b30060e6467f 100644 (file)
@@ -39,23 +39,38 @@ class QPaintEvent;
 #endif
 
 namespace lyx {
+
+class Buffer;
+
 namespace frontend {
 
+class LyXView;
+
+/// types of cursor in work area
+enum CursorShape {
+       /// normal I-beam
+       BAR_SHAPE,
+       /// L-shape for locked insets of a different language
+       L_SHAPE,
+       /// reverse L-shape for RTL text
+       REVERSED_L_SHAPE
+};
+
 /// for emulating triple click
-class double_click {
+class DoubleClick {
 public:
+       ///
+       DoubleClick() : state(Qt::NoButton), active(false) {}
+       ///
+       DoubleClick(QMouseEvent * e) : state(e->button()), active(true) {}
+       ///
+       bool operator==(QMouseEvent const & e) { return state == e.button(); }
+       ///
+public:
+       ///
        Qt::MouseButton state;
+       ///
        bool active;
-
-       bool operator==(QMouseEvent const & e) {
-               return state == e.button();
-       }
-
-       double_click()
-               : state(Qt::NoButton), active(false) {}
-
-       double_click(QMouseEvent * e)
-               : state(e->button()), active(true) {}
 };
 
 /** Qt only emits mouse events when the mouse is being moved, but
@@ -79,11 +94,12 @@ public:
        double scrollbar_value_old;
 };
 
+
 /**
- * Qt-specific implementation of the work area
- * (buffer view GUI)
+ * Implementation of the work area (buffer view GUI)
 */
-       class CursorWidget;
+class CursorWidget;
+
 class GuiWorkArea : public QAbstractScrollArea, public WorkArea
 {
        Q_OBJECT
@@ -91,6 +107,8 @@ class GuiWorkArea : public QAbstractScrollArea, public WorkArea
 public:
        ///
        GuiWorkArea(Buffer & buffer, LyXView & lv);
+       ///
+       ~GuiWorkArea();
 
        ///
        bool hasFocus() const { return QAbstractScrollArea::hasFocus(); }
@@ -116,7 +134,36 @@ public:
 
        /// hide the cursor
        virtual void removeCursor();
+       ///
+       void setLyXView(LyXView & lv) { lyx_view_ = &lv; }
+       ///
+       BufferView & bufferView();
+       ///
+       BufferView const & bufferView() const;
+       ///
+       void redraw();
+       ///
+       void stopBlinkingCursor();
+       ///
+       void startBlinkingCursor();
+       ///
+       void processKeySym(KeySymbol const & key, KeyModifier mod);
 
+public Q_SLOTS:
+       /// Adjust the LyX buffer view with the position of the scrollbar.
+       /**
+       * The action argument is not used in the the code, it is there
+       * only for the connection to the vertical srollbar signal which
+       * emits an 'int' action.
+       */
+       void adjustViewWithScrollBar(int action = 0);
+       /// timer to limit triple clicks
+       void doubleClickTimeout();
+
+       /// close this work area.
+       /// Slot for Buffer::closing signal.
+       void close();
+       ////
        void setWindowTitle(docstring const & t, docstring const & it);
 
 Q_SIGNALS:
@@ -124,6 +171,11 @@ Q_SIGNALS:
        void titleChanged(GuiWorkArea *);
 
 private:
+       /// This function is called when the buffer readonly status change.
+       void setReadOnly(bool);
+
+       /// Update window titles of all users.
+       void updateWindowTitle();
        ///
        void focusInEvent(QFocusEvent *);
        ///
@@ -149,25 +201,34 @@ private:
        /// IM query
        QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
 
-public Q_SLOTS:
-       /// Adjust the LyX buffer view with the position of the scrollbar.
-       /**
-       * The action argument is not used in the the code, it is there
-       * only for the connection to the vertical srollbar signal which
-       * emits an 'int' action.
-       */
-       void adjustViewWithScrollBar(int action = 0);
-       /// timer to limit triple clicks
-       void doubleClickTimeout();
-
-private:
        /// The slot connected to SyntheticMouseEvent::timeout.
        void generateSyntheticMouseEvent();
+       ///
+       void dispatch(FuncRequest const & cmd0, KeyModifier = NoModifier);
+       ///
+       void resizeBufferView();
+       /// hide the visible cursor, if it is visible
+       void hideCursor();
+       /// show the cursor if it is not visible
+       void showCursor();
+       /// toggle the cursor's visibility
+       void toggleCursor();
+       ///
+       void updateScrollbar();
 
+       ///
+       BufferView * buffer_view_;
+       ///
+       LyXView * lyx_view_;
+       /// is the cursor currently displayed
+       bool cursor_visible_;
+
+       ///
+       Timeout cursor_timeout_;
        ///
        SyntheticMouseEvent synthetic_mouse_event_;
        ///
-       double_click dc_event_;
+       DoubleClick dc_event_;
 
        ///
        CursorWidget * cursor_;
@@ -181,7 +242,8 @@ private:
        bool schedule_redraw_;
        ///
        int preedit_lines_;
-}; //GuiWorkArea
+}; // GuiWorkArea
+
 
 /// A tabbed set of GuiWorkAreas.
 class TabWorkArea : public QTabWidget