From: Abdelrazak Younes Date: Tue, 20 Jun 2006 08:39:16 +0000 (+0000) Subject: This is the merging of the GUI API cleanup branch that was developed in svn+ssh:... X-Git-Tag: 1.6.10~13091 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=d8ae51dbe178d6b10a56c747cfd399a4dbba8117;p=features.git This is the merging of the GUI API cleanup branch that was developed in svn+ssh://svn.lyx.org/lyx/lyx-devel/branches/personal/younes. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@14152 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/development/scons/SConstruct b/development/scons/SConstruct index 6b19d5b4f9..d496f40a4a 100644 --- a/development/scons/SConstruct +++ b/development/scons/SConstruct @@ -1983,7 +1983,7 @@ if build_qt4: QtView.C QURLDialog.C QVSpaceDialog.C - QWorkArea.C + GuiWorkArea.C QWrapDialog.C QLToolbar.C socket_callback.C diff --git a/src/BufferView.C b/src/BufferView.C index cbe6a33ef9..d52233651d 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -39,9 +39,10 @@ #include "WordLangTuple.h" #include "frontends/Alert.h" +#include "frontends/Clipboard.h" #include "frontends/Dialogs.h" #include "frontends/LyXView.h" -#include "frontends/screen.h" +#include "frontends/Gui.h" #include "frontends/WorkArea.h" #include "insets/insetcommand.h" // ChangeRefs @@ -83,19 +84,13 @@ Buffer * BufferView::buffer() const } -LyXScreen & BufferView::screen() const -{ - return pimpl_->screen(); -} - - LyXView * BufferView::owner() const { return pimpl_->owner_; } -Painter & BufferView::painter() const +lyx::frontend::Painter & BufferView::painter() const { return pimpl_->painter(); } @@ -200,7 +195,7 @@ void BufferView::switchKeyMap() int BufferView::workWidth() const { - return pimpl_->workarea().workWidth(); + return pimpl_->workarea().width(); } @@ -212,7 +207,7 @@ void BufferView::center() string const BufferView::getClipboard() const { - return pimpl_->workarea().getClipboard(); + return pimpl_->clipboard().get(); } @@ -317,7 +312,7 @@ void BufferView::gotoLabel(string const & label) void BufferView::hideCursor() { - screen().hideCursor(); + pimpl_->gui().guiCursor().hide(); } LyXText * BufferView::getLyXText() @@ -338,13 +333,13 @@ LyXText const * BufferView::getLyXText() const void BufferView::haveSelection(bool sel) { - pimpl_->workarea().haveSelection(sel); + pimpl_->clipboard().haveSelection(sel); } int BufferView::workHeight() const { - return pimpl_->workarea().workHeight(); + return pimpl_->workarea().height(); } diff --git a/src/BufferView.h b/src/BufferView.h index 1c79d7cfad..5723cb72cd 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -32,11 +32,14 @@ class FuncStatus; class Language; class LCursor; class LyXText; -class LyXScreen; class LyXView; -class Painter; class ParIterator; +namespace lyx { +namespace frontend { +class Painter; +} +} namespace Update { enum flags { @@ -83,9 +86,8 @@ public: Buffer * buffer() const; /// return the painter object for drawing onto the view - Painter & painter() const; - /// return the screen object for handling re-drawing - LyXScreen & screen() const; + lyx::frontend::Painter & painter() const; + /// return the owning main view LyXView * owner() const; diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index de0508b19d..0976075911 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -58,14 +58,14 @@ #include "insets/insettext.h" #include "frontends/Alert.h" +#include "frontends/Clipboard.h" #include "frontends/Dialogs.h" #include "frontends/FileDialog.h" #include "frontends/font_metrics.h" +#include "frontends/Gui.h" #include "frontends/LyXView.h" -#include "frontends/LyXScreenFactory.h" -#include "frontends/screen.h" +#include "frontends/Painter.h" #include "frontends/WorkArea.h" -#include "frontends/WorkAreaFactory.h" #include "graphics/Previews.h" @@ -82,6 +82,10 @@ #include #include +using lyx::frontend::WorkArea; +using lyx::frontend::Clipboard; +using lyx::frontend::Gui; + using lyx::pos_type; using lyx::support::addPath; @@ -103,7 +107,6 @@ using std::string; using std::mem_fun_ref; using std::vector; - extern BufferList bufferlist; @@ -142,13 +145,13 @@ BufferView::Pimpl::Pimpl(BufferView & bv, LyXView * owner, { xsel_cache_.set = false; - workarea_.reset(WorkAreaFactory::create(*owner_, width, height)); - screen_.reset(LyXScreenFactory::create(workarea())); + workAreaId_ = owner_->gui().newWorkArea(width, height); + workArea_ = & owner_->gui().workArea(workAreaId_); // Setup the signals timecon = cursor_timeout.timeout .connect(boost::bind(&BufferView::Pimpl::cursorToggle, this)); - + cursor_timeout.start(); saved_positions.resize(saved_positions_num); @@ -314,21 +317,27 @@ bool BufferView::Pimpl::loadLyXFile(string const & filename, bool tolastfiles) } -WorkArea & BufferView::Pimpl::workarea() const +lyx::frontend::Gui & BufferView::Pimpl::gui() const +{ + return owner_->gui(); +} + + +lyx::frontend::WorkArea & BufferView::Pimpl::workarea() const { - return *workarea_.get(); + return *workArea_; } -LyXScreen & BufferView::Pimpl::screen() const +lyx::frontend::Clipboard & BufferView::Pimpl::clipboard() const { - return *screen_.get(); + return owner_->gui().clipboard(); } -Painter & BufferView::Pimpl::painter() const +lyx::frontend::Painter & BufferView::Pimpl::painter() const { - return workarea().getPainter(); + return workArea_->getPainter(); } @@ -451,7 +460,7 @@ void BufferView::Pimpl::updateScrollbar() if (!bv_->text()) { lyxerr[Debug::DEBUG] << BOOST_CURRENT_FUNCTION << " no text in updateScrollbar" << endl; - workarea().setScrollbarParams(0, 0, 0); + workArea_->setScrollbarParams(0, 0, 0); return; } @@ -473,7 +482,7 @@ void BufferView::Pimpl::updateScrollbar() // estimated average paragraph height: if (wh_ == 0) - wh_ = workarea().workHeight() / 4; + wh_ = workArea_->height() / 4; int h = t.getPar(anchor_ref_).height(); // Normalize anchor/offset (MV): @@ -486,7 +495,7 @@ void BufferView::Pimpl::updateScrollbar() int sumh = 0; int nh = 0; for (lyx::pit_type pit = anchor_ref_; pit <= parsize; ++pit) { - if (sumh > workarea().workHeight()) + if (sumh > workArea_->height()) break; int const h2 = t.getPar(pit).height(); sumh += h2; @@ -497,7 +506,7 @@ void BufferView::Pimpl::updateScrollbar() if (hav > wh_) wh_ = hav; - workarea().setScrollbarParams((parsize + 1) * wh_, + workArea_->setScrollbarParams((parsize + 1) * wh_, anchor_ref_ * wh_ + int(offset_ref_ * wh_ / float(h)), int(wh_ * defaultRowHeight() / float(h))); } @@ -511,7 +520,7 @@ void BufferView::Pimpl::scrollDocView(int value) if (!buffer_) return; - screen().hideCursor(); + owner_->gui().guiCursor().hide(); LyXText & t = *bv_->text(); @@ -530,7 +539,7 @@ void BufferView::Pimpl::scrollDocView(int value) int const height = 2 * defaultRowHeight(); int const first = height; - int const last = workarea().workHeight() - height; + int const last = workArea_->height() - height; LCursor & cur = cursor_; bv_funcs::CurStatus st = bv_funcs::status(bv_, cur); @@ -574,7 +583,7 @@ void BufferView::Pimpl::scroll(int /*lines*/) // scrollDocView(new_top_y); // // // Update the scrollbar. -// workarea().setScrollbarParams(t->height(), top_y(), defaultRowHeight()); +// workArea_->.setScrollbarParams(t->height(), top_y(), defaultRowHeight()); } @@ -591,7 +600,7 @@ void BufferView::Pimpl::workAreaKeyPress(LyXKeySymPtr key, * dispatch() itself, because that's called recursively. */ if (available()) - screen().showCursor(*bv_); + owner_->gui().guiCursor().show(*bv_); } @@ -618,7 +627,7 @@ void BufferView::Pimpl::selectionRequested() xsel_cache_.set = cur.selection(); sel = cur.selectionAsString(false); if (!sel.empty()) - workarea().putClipboard(sel); + clipboard().put(sel); } } @@ -626,7 +635,7 @@ void BufferView::Pimpl::selectionRequested() void BufferView::Pimpl::selectionLost() { if (available()) { - screen().hideCursor(); + owner_->gui().guiCursor().hide(); cursor_.clearSelection(); xsel_cache_.set = false; } @@ -635,15 +644,15 @@ void BufferView::Pimpl::selectionLost() void BufferView::Pimpl::workAreaResize() { - static int work_area_width; - static int work_area_height; + static int workArea_width; + static int workArea_height; - bool const widthChange = workarea().workWidth() != work_area_width; - bool const heightChange = workarea().workHeight() != work_area_height; + bool const widthChange = workArea_->width() != workArea_width; + bool const heightChange = workArea_->height() != workArea_height; // Update from work area - work_area_width = workarea().workWidth(); - work_area_height = workarea().workHeight(); + workArea_width = workArea_->width(); + workArea_height = workArea_->height(); if (buffer_ && widthChange) { // The visible LyXView need a resize @@ -666,7 +675,7 @@ bool BufferView::Pimpl::fitCursor() int const asc = font_metrics::maxAscent(font); int const des = font_metrics::maxDescent(font); Point const p = bv_funcs::getPos(cursor_, cursor_.boundary()); - if (p.y_ - asc >= 0 && p.y_ + des < workarea().workHeight()) + if (p.y_ - asc >= 0 && p.y_ + des < workArea_->height()) return false; } center(); @@ -721,14 +730,14 @@ void BufferView::Pimpl::update(Update::flags flags) } if (forceupdate) { // Second drawing step - screen().redraw(*bv_, vi); + workArea_->redraw(*bv_, vi); } else { // Abort updating of the coord // cache - just restore the old one std::swap(theCoords, backup); } } else - screen().greyOut(); + workArea_->greyOut(); // And the scrollbar updateScrollbar(); @@ -740,7 +749,7 @@ void BufferView::Pimpl::update(Update::flags flags) void BufferView::Pimpl::cursorToggle() { if (buffer_) { - screen().toggleCursor(*bv_); + owner_->gui().guiCursor().toggle(*bv_); // Use this opportunity to deal with any child processes that // have finished but are waiting to communicate this fact @@ -867,13 +876,13 @@ void BufferView::Pimpl::center() Paragraph const & par = bot.text()->paragraphs()[pit]; anchor_ref_ = pit; offset_ref_ = bv_funcs::coordOffset(cursor_, cursor_.boundary()).y_ - + par.ascent() - workarea().workHeight() / 2; + + par.ascent() - workArea_->height() / 2; } void BufferView::Pimpl::stuffClipboard(string const & content) const { - workarea().putClipboard(content); + clipboard().put(content); } @@ -998,13 +1007,13 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0) if (!available()) return false; - screen().hideCursor(); + owner_->gui().guiCursor().hide(); // Either the inset under the cursor or the // surrounding LyXText will handle this event. // Build temporary cursor. - cmd.y = min(max(cmd.y,-1), workarea().workHeight()); + cmd.y = min(max(cmd.y, -1), workArea_->height()); InsetBase * inset = bv_->text()->editXY(cur, cmd.x, cmd.y); //lyxerr << BOOST_CURRENT_FUNCTION // << " * hit inset at tip: " << inset << endl; @@ -1036,7 +1045,7 @@ bool BufferView::Pimpl::workAreaDispatch(FuncRequest const & cmd0) // See workAreaKeyPress cursor_timeout.restart(); - screen().showCursor(*bv_); + owner_->gui().guiCursor().show(*bv_); // Skip these when selecting if (cmd.action != LFUN_MOUSE_MOTION) { diff --git a/src/BufferView_pimpl.h b/src/BufferView_pimpl.h index 20f131c789..bf66462773 100644 --- a/src/BufferView_pimpl.h +++ b/src/BufferView_pimpl.h @@ -34,16 +34,24 @@ #include #include - class Change; class LyXKeySym; class LyXView; -class WorkArea; -class LyXScreen; + class FuncRequest; class FuncStatus; class ViewMetricsInfo; +namespace lyx { +namespace frontend { +class Gui; +class WorkArea; +class Clipboard; +class Painter; +class GuiCursor; +} +} + /// class BufferView::Pimpl : public boost::signals::trackable { @@ -51,9 +59,7 @@ public: /// Pimpl(BufferView & bv, LyXView * owner, int width, int height); /// - Painter & painter() const; - /// return the screen for this bview - LyXScreen & screen() const; + lyx::frontend::Painter & painter() const; /// void setBuffer(Buffer * buf); /// @@ -110,6 +116,14 @@ public: bool repaintAll() { return refresh_inside_; } /// void repaintAll(bool r) {refresh_inside_ = r; } + + /// the frontend + lyx::frontend::Gui & gui() const; + /// our workarea + lyx::frontend::WorkArea & workarea() const; + /// the clipboard + lyx::frontend::Clipboard & clipboard() const; + private: /// An error list (replaces the error insets) ErrorList errorlist_; @@ -148,10 +162,7 @@ private: LyXView * owner_; /// Buffer * buffer_; - /// - boost::scoped_ptr screen_; - /// - boost::scoped_ptr workarea_; + /// Estimated average par height for scrollbar int wh_; /// @@ -179,8 +190,10 @@ private: std::vector saved_positions; /// void menuInsertLyXFile(std::string const & filen); - /// our workarea - WorkArea & workarea() const; + + lyx::frontend::WorkArea * workArea_; + int workAreaId_; + /// this is used to handle XSelection events in the right manner struct { CursorSlice cursor; diff --git a/src/frontends/Clipboard.h b/src/frontends/Clipboard.h new file mode 100644 index 0000000000..ca046429fe --- /dev/null +++ b/src/frontends/Clipboard.h @@ -0,0 +1,41 @@ +// -*- C++ -*- +/** + * \file Clipboard.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author unknown + * \author John Levon + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef BASE_CLIPBOARD_H +#define BASE_CLIPBOARD_H + +#include + +namespace lyx { +namespace frontend { + +/** + * A Clipboard class manages the clipboard. + */ +class Clipboard +{ +public: + virtual ~Clipboard() {} + + /// a selection exists + virtual void haveSelection(bool) = 0; + /// get the X clipboard contents + virtual std::string const get() const = 0; + /// fill the clipboard + virtual void put(std::string const &) = 0; +}; + +} // namespace frontend +} // namespace lyx + +#endif // BASE_CLIPBOARD_H diff --git a/src/frontends/Gui.h b/src/frontends/Gui.h new file mode 100644 index 0000000000..2d1c9eee1e --- /dev/null +++ b/src/frontends/Gui.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +/** + * \file Gui.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author unknown + * \author John Levon + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef BASE_GUI_H +#define BASE_GUI_H + +#include "frontends/GuiCursor.h" + +namespace lyx { +namespace frontend { + +class Clipboard; +class WorkArea; + + +/** + * A Gui class manages the different frontend elements. + */ +class Gui +{ +public: + virtual ~Gui() {} + + /// + virtual Clipboard& clipboard() = 0; + /// + virtual int newWorkArea(int w, int h) = 0; + /// + virtual WorkArea& workArea(int id) = 0; + /// + virtual void destroyWorkArea(int id) = 0; + + /// + GuiCursor & guiCursor() {return cursor_;} + +private: + GuiCursor cursor_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // BASE_GUI_H diff --git a/src/frontends/GuiCursor.C b/src/frontends/GuiCursor.C new file mode 100644 index 0000000000..7187c49746 --- /dev/null +++ b/src/frontends/GuiCursor.C @@ -0,0 +1,149 @@ +/** + * \file GuiCursor.C + * 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 + +#include "frontends/GuiCursor.h" + +#include "font_metrics.h" +#include "lyx_gui.h" +#include "frontends/Painter.h" +#include "frontends/WorkArea.h" + +#include "BufferView.h" +#include "buffer.h" +#include "bufferparams.h" +#include "coordcache.h" +#include "cursor.h" +#include "debug.h" +#include "language.h" +#include "LColor.h" +#include "lyxfont.h" +#include "lyxrc.h" +#include "lyxrow.h" +#include "lyxtext.h" +#include "metricsinfo.h" +#include "paragraph.h" +#include "rowpainter.h" +#include "version.h" + +#include "graphics/GraphicsImage.h" +#include "graphics/GraphicsLoader.h" + +#include "support/filetools.h" // LibFileSearch + +#include +#include +#include + +using lyx::support::libFileSearch; + +using std::endl; +using std::min; +using std::max; +using std::string; + +namespace lyx { +namespace frontend { + +GuiCursor::GuiCursor() + : cursor_visible_(false), work_area_(NULL) +{ +} + + +GuiCursor::~GuiCursor() +{ +} + +void GuiCursor::connect(WorkArea * work_area) +{ + work_area_ = work_area; +} + + +void GuiCursor::show(BufferView & bv) +{ + if (cursor_visible_) + return; + + if (!bv.available()) + return; + + Cursor_Shape shape = BAR_SHAPE; + + LyXText const & text = *bv.getLyXText(); + LyXFont const & realfont = text.real_current_font; + BufferParams const & bp = bv.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; + + LyXFont const font = bv.cursor().getFont(); + int const asc = font_metrics::maxAscent(font); + int const des = font_metrics::maxDescent(font); + int h = asc + des; + int x = 0; + int y = 0; + bv.cursor().getPos(x, y); + y -= asc; + //lyxerr << "Cursor::show x: " << x << " y: " << y << endl; + + BOOST_ASSERT(work_area_); + + // if it doesn't touch the screen, don't try to show it + if (y + h < 0 || y >= work_area_->height()) + return; + + cursor_visible_ = true; + work_area_->showCursor(x, y, h, shape); +} + + +void GuiCursor::hide() +{ + if (!cursor_visible_) + return; + + cursor_visible_ = false; + BOOST_ASSERT(work_area_); + work_area_->removeCursor(); +} + + +void GuiCursor::toggle(BufferView & bv) +{ + if (cursor_visible_) + hide(); + else + show(bv); +} + + +void GuiCursor::prepare() +{ + cursor_visible_ = false; +} + +} // namespace frontend +} // namespace lyx + diff --git a/src/frontends/GuiCursor.h b/src/frontends/GuiCursor.h new file mode 100644 index 0000000000..cc45d8c143 --- /dev/null +++ b/src/frontends/GuiCursor.h @@ -0,0 +1,73 @@ +// -*- C++ -*- +/** + * \file GuiCursor.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author unknown + * \author John Levon + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef GUI_CURSOR_H +#define GUI_CURSOR_H + + +class LyXText; +class CursorSlice; +class BufferView; +class ViewMetricsInfo; + +namespace lyx { +namespace frontend { + +class WorkArea; + +/// types of cursor in work area +enum Cursor_Shape { + /// 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 +}; + +/** + * GuiCursor - document rendering management + * + * The blinking cursor is handled here. + */ +class GuiCursor { +public: + GuiCursor(); + + virtual ~GuiCursor(); + + void connect(WorkArea * work_area); + + /// hide the visible cursor, if it is visible + void hide(); + + /// show the cursor if it is not visible + void show(BufferView & bv); + + /// toggle the cursor's visibility + void toggle(BufferView & bv); + + /// set cursor_visible_ to false in prep for re-display + void prepare(); + +private: + /// is the cursor currently displayed + bool cursor_visible_; + + WorkArea * work_area_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // GUI_CURSOR_H diff --git a/src/frontends/LyXScreenFactory.h b/src/frontends/LyXScreenFactory.h deleted file mode 100644 index 70057d3d03..0000000000 --- a/src/frontends/LyXScreenFactory.h +++ /dev/null @@ -1,26 +0,0 @@ -// -*- C++ -*- -/** - * \file LyXScreenFactory.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef LYXSCREENFACTORY_H -#define LYXSCREENFACTORY_H - -class WorkArea; -class LyXScreen; - -namespace LyXScreenFactory { - /** - * Make a screen renderer. Used because we want to - * generate a toolkit-specific instance. - */ - LyXScreen * create(WorkArea & owner); -} - -#endif // LYXSCREEN_FACTORY_H diff --git a/src/frontends/LyXView.h b/src/frontends/LyXView.h index c43dc71186..29e51c1dbf 100644 --- a/src/frontends/LyXView.h +++ b/src/frontends/LyXView.h @@ -33,9 +33,15 @@ class Timeout; class FuncRequest; namespace lyx { + +namespace frontend { +class Gui; +} // namespace frontend + namespace frontend { class ControlCommandBuffer; } // namespace frontend + } // namespace lyx /** @@ -145,6 +151,8 @@ public: // returns true if this view has the focus. virtual bool hasFocus() const = 0; + virtual lyx::frontend::Gui & gui() = 0; + protected: /// view of a buffer. Eventually there will be several. boost::shared_ptr bufferview_; diff --git a/src/frontends/Makefile.am b/src/frontends/Makefile.am index aba9061230..eda5f688e2 100644 --- a/src/frontends/Makefile.am +++ b/src/frontends/Makefile.am @@ -21,7 +21,6 @@ libfrontends_la_SOURCES = \ FileDialog.h \ LyXKeySym.h \ LyXKeySymFactory.h \ - LyXScreenFactory.h \ LyXView.C \ LyXView.h \ Menubar.h \ @@ -31,8 +30,12 @@ libfrontends_la_SOURCES = \ Timeout.h \ Toolbars.C \ Toolbars.h \ + Clipboard.h \ + Gui.h \ + GuiCursor.C \ + GuiCursor.h \ + WorkArea.C \ WorkArea.h \ - WorkAreaFactory.h \ font_metrics.h \ guiapi.h \ guiapi.C \ @@ -40,6 +43,4 @@ libfrontends_la_SOURCES = \ lyx_gui.h \ mouse_state.h \ nullpainter.C \ - nullpainter.h \ - screen.C \ - screen.h + nullpainter.h diff --git a/src/frontends/Painter.C b/src/frontends/Painter.C index 9a1eab7912..a3b14ff624 100644 --- a/src/frontends/Painter.C +++ b/src/frontends/Painter.C @@ -13,7 +13,6 @@ #include "Painter.h" #include "font_metrics.h" -#include "WorkArea.h" #include "LColor.h" #include "lyxfont.h" @@ -21,6 +20,8 @@ using std::max; using std::string; +namespace lyx { +namespace frontend { void Painter::button(int x, int y, int w, int h) { @@ -92,3 +93,6 @@ void Painter::underline(LyXFont const & f, int x, int y, int width) else fillRectangle(x, y + below, width, below + height, f.color()); } + +} // namespace frontend +} // namespace lyx diff --git a/src/frontends/Painter.h b/src/frontends/Painter.h index 668ec4b9b8..9680acb2e2 100644 --- a/src/frontends/Painter.h +++ b/src/frontends/Painter.h @@ -26,8 +26,8 @@ namespace lyx { namespace graphics { class Image; } -} +namespace frontend { /** * Painter - A painter class to encapsulate all graphics parameters and operations @@ -182,4 +182,7 @@ protected: virtual void buttonFrame(int x, int y, int w, int h); }; +} // namespace frontend +} // namespace lyx + #endif // PAINTER_H diff --git a/src/frontends/WorkArea.C b/src/frontends/WorkArea.C new file mode 100644 index 0000000000..9f20119a5f --- /dev/null +++ b/src/frontends/WorkArea.C @@ -0,0 +1,187 @@ +/** + * \file WorkArea.C + * 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 + +#include "WorkArea.h" + +#include "font_metrics.h" +#include "lyx_gui.h" +#include "Painter.h" + +#include "BufferView.h" +#include "buffer.h" +#include "bufferparams.h" +#include "coordcache.h" +#include "cursor.h" +#include "debug.h" +#include "language.h" +#include "LColor.h" +#include "lyxfont.h" +#include "lyxrc.h" +#include "lyxrow.h" +#include "lyxtext.h" +#include "metricsinfo.h" +#include "paragraph.h" +#include "rowpainter.h" +#include "version.h" + +#include "graphics/GraphicsImage.h" +#include "graphics/GraphicsLoader.h" + +#include "support/filetools.h" // LibFileSearch + +#include +#include +#include + +using lyx::support::libFileSearch; + +using std::endl; +using std::min; +using std::max; +using std::string; + + +namespace lyx { +namespace frontend { + +class SplashScreen : boost::noncopyable, boost::signals::trackable { +public: + /// This is a singleton class. Get the instance. + static SplashScreen const & get(); + /// + lyx::graphics::Image const * image() const { return loader_.image(); } + /// + string const & text() const { return text_; } + /// + LyXFont const & font() const { return font_; } + /// + void connect(lyx::graphics::Loader::slot_type const & slot) const { + loader_.connect(slot); + } + /// + void startLoading() const { + if (loader_.status() == lyx::graphics::WaitingToLoad) + loader_.startLoading(); + } + +private: + /** Make the c-tor private so we can control how many objects + * are instantiated. + */ + SplashScreen(); + + /// + lyx::graphics::Loader loader_; + /// The text to be written on top of the pixmap + string const text_; + /// in this font... + LyXFont font_; +}; + + +SplashScreen const & SplashScreen::get() +{ + static SplashScreen singleton; + return singleton; +} + + +SplashScreen::SplashScreen() + : text_(lyx_version ? lyx_version : "unknown") +{ + if (!lyxrc.show_banner) + return; + + string const file = libFileSearch("images", "banner", "ppm"); + if (file.empty()) + return; + + // The font used to display the version info + font_.setFamily(LyXFont::SANS_FAMILY); + font_.setSeries(LyXFont::BOLD_SERIES); + font_.setSize(LyXFont::SIZE_NORMAL); + font_.setColor(LColor::yellow); + + // Load up the graphics file + loader_.reset(file); +} + +WorkArea::WorkArea(LyXView & owner, int w, int h) + : greyed_out_(true) +{ + // Start loading the pixmap as soon as possible + if (lyxrc.show_banner) { + SplashScreen const & splash = SplashScreen::get(); + splash.connect(boost::bind(&WorkArea::checkAndGreyOut, this)); + splash.startLoading(); + } +} + + +void WorkArea::checkAndGreyOut() +{ + if (greyed_out_) + greyOut(); +} + + +void WorkArea::redraw(BufferView & bv, ViewMetricsInfo const & vi) +{ + greyed_out_ = false; + getPainter().start(); + paintText(bv, vi); + lyxerr[Debug::DEBUG] << "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); + getPainter().end(); + theCoords.doneUpdating(); +} + + +void WorkArea::greyOut() +{ + greyed_out_ = true; + getPainter().start(); + + getPainter().fillRectangle(0, 0, + width(), + height(), + LColor::bottomarea); + + // Add a splash screen to the centre of the work area + SplashScreen const & splash = SplashScreen::get(); + lyx::graphics::Image const * const splash_image = splash.image(); + if (splash_image) { + int const w = splash_image->getWidth(); + int const h = splash_image->getHeight(); + + int x = (width() - w) / 2; + int y = (height() - h) / 2; + + getPainter().image(x, y, w, h, *splash_image); + + x += 260; + y += 265; + + getPainter().text(x, y, splash.text(), splash.font()); + } + expose(0, 0, width(), height()); + getPainter().end(); +} + +} // namespace frontend +} // namespace lyx diff --git a/src/frontends/WorkArea.h b/src/frontends/WorkArea.h index f48dbd0403..b3ee602e57 100644 --- a/src/frontends/WorkArea.h +++ b/src/frontends/WorkArea.h @@ -6,32 +6,39 @@ * * \author unknown * \author John Levon + * \author Abdelrazak Younes * * Full author contact details are available in file CREDITS. */ -#ifndef WORKAREA_H -#define WORKAREA_H +#ifndef BASE_WORKAREA_H +#define BASE_WORKAREA_H + +#include "frontends/GuiCursor.h" #include "frontends/key_state.h" #include "frontends/LyXKeySym.h" -#include +class LyXView; +class FuncRequest; +class BufferView; +class ViewMetricsInfo; +namespace lyx { +namespace frontend { class Painter; -class FuncRequest; /** * The work area class represents the widget that provides the * view onto a document. It is owned by the BufferView, and * is responsible for handing events back to its owning BufferView. - * It works in concert with the LyXScreen class to update the + * It works in concert with the BaseScreen class to update the * widget view of a document. */ class WorkArea { public: - WorkArea() {} + WorkArea(LyXView & owner, int w, int h); virtual ~WorkArea() {} @@ -39,9 +46,10 @@ public: virtual Painter & getPainter() = 0; /// return the width of the work area in pixels - virtual int workWidth() const = 0; + virtual int width() const = 0; + /// return the height of the work area in pixels - virtual int workHeight() const = 0; + virtual int height() const = 0; /** * Update the scrollbar. @@ -51,13 +59,31 @@ public: */ virtual void setScrollbarParams(int height, int pos, int line_height) = 0; - // FIXME: this is an odd place to have it, but xforms needs it here ... - /// a selection exists - virtual void haveSelection(bool) const = 0; - /// get the X clipboard contents - virtual std::string const getClipboard() const = 0; - /// fill the clipboard - virtual void putClipboard(std::string const &) const = 0; + /// redraw the screen, without using existing pixmap + virtual void redraw(BufferView & bv, ViewMetricsInfo const & vi); + + /// grey out (no buffer) + void greyOut(); + + /// paint the cursor and store the background + virtual void showCursor(int x, int y, int h, Cursor_Shape shape) = 0; + + /// hide the cursor + virtual void removeCursor() = 0; + +protected: + /// cause the display of the given area of the work area + virtual void expose(int x, int y, int w, int h) = 0; + +private: + /// + void checkAndGreyOut(); + + /// + bool greyed_out_; }; -#endif // WORKAREA_H +} // namespace frontend +} // namespace lyx + +#endif // BASE_WORKAREA_H diff --git a/src/frontends/WorkAreaFactory.h b/src/frontends/WorkAreaFactory.h deleted file mode 100644 index ca679bf6ef..0000000000 --- a/src/frontends/WorkAreaFactory.h +++ /dev/null @@ -1,26 +0,0 @@ -// -*- C++ -*- -/** - * \file WorkAreaFactory.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef WORKAREAFACTORY_H -#define WORKAREAFACTORY_H - -class WorkArea; -class LyXView; - -namespace WorkAreaFactory { - /** - * Make a work area. Used because we want to generate - * a toolkit-specific instance. - */ - WorkArea * create(LyXView & owner, int w, int h); -} - -#endif // WORKAREA_FACTORY_H diff --git a/src/frontends/gtk/GScreen.C b/src/frontends/gtk/GScreen.C index ee711bba9c..2014e73463 100644 --- a/src/frontends/gtk/GScreen.C +++ b/src/frontends/gtk/GScreen.C @@ -30,10 +30,8 @@ #include "lyxtext.h" #include "lyxrow.h" -#include "frontends/screen.h" #include "frontends/font_metrics.h" #include "frontends/Painter.h" -#include "frontends/WorkArea.h" #include "insets/insettext.h" @@ -43,7 +41,7 @@ namespace lyx { namespace frontend { GScreen::GScreen(GWorkArea & o) - : LyXScreen(), owner_(o) + : owner_(o) { // the cursor isnt yet visible cursorX_ = 0; @@ -58,12 +56,6 @@ GScreen::~GScreen() } -WorkArea & GScreen::workarea() -{ - return owner_; -} - - void GScreen::setCursorColor(Glib::RefPtr gc) { Gdk::Color * clr = owner_.getColorHandler(). diff --git a/src/frontends/gtk/GScreen.h b/src/frontends/gtk/GScreen.h index baaea7e3f5..8e9a169454 100644 --- a/src/frontends/gtk/GScreen.h +++ b/src/frontends/gtk/GScreen.h @@ -12,7 +12,7 @@ #ifndef GSCREEN_H #define GSCREEN_H -#include "screen.h" +#include "frontends/GuiCursor.h" #include @@ -26,7 +26,7 @@ class GWorkArea; date and used to optimize drawing on the screen. This class also handles the drawing of the cursor and partly the selection. */ -class GScreen : public LyXScreen { +class GScreen { public: /// GScreen(GWorkArea &); @@ -40,9 +40,6 @@ public: virtual void removeCursor(); /// virtual void showCursor(int x, int y, int h, Cursor_Shape shape); -protected: - /// get the work area - virtual WorkArea & workarea(); /// Copies specified area of pixmap to screen virtual void expose(int x, int y, int w, int h); diff --git a/src/frontends/gtk/GView.C b/src/frontends/gtk/GView.C index d3a29ec16e..f07b198315 100644 --- a/src/frontends/gtk/GView.C +++ b/src/frontends/gtk/GView.C @@ -57,7 +57,7 @@ void add_el(Gtk::Box::BoxList & list, Gtk::Box & box, bool shrink) } // namespace anon -GView::GView() +GView::GView() : frontend_(*this) { // The physical store for the boxes making up the layout. box_store_.push_back(BoxPtr(new Gtk::VBox)); diff --git a/src/frontends/gtk/GView.h b/src/frontends/gtk/GView.h index 2b74894cb1..cc796a66f3 100644 --- a/src/frontends/gtk/GView.h +++ b/src/frontends/gtk/GView.h @@ -12,9 +12,12 @@ #ifndef GVIEW_H #define GVIEW_H -#include "frontends/LyXView.h" #include "bufferview_funcs.h" +#include "frontends/LyXView.h" + +#include "GuiImplementation.h" + #include #include @@ -55,6 +58,9 @@ public: // returns true if this view has the focus. virtual bool hasFocus() const; + /// + Gui & gui() { return frontend_; } + private: void showViewState(); bool onFocusIn(GdkEventFocus * event); @@ -73,6 +79,8 @@ private: boost::scoped_ptr minibuffer_; Gtk::Widget * workArea_; + /// + GuiImplementation frontend_; }; } // namespace frontend diff --git a/src/frontends/gtk/GWorkArea.C b/src/frontends/gtk/GWorkArea.C index 5cdae14731..0b39199cb5 100644 --- a/src/frontends/gtk/GWorkArea.C +++ b/src/frontends/gtk/GWorkArea.C @@ -504,7 +504,7 @@ void GWorkArea::onClipboardClear() } -void GWorkArea::haveSelection(bool toHave) const +void GWorkArea::haveSelection(bool toHave) { if (toHave) { Glib::RefPtr clipboard = @@ -533,7 +533,7 @@ string const GWorkArea::getClipboard() const // ENCODING: we assume that the backend passes us ISO-8859-1 and // convert from that to UTF-8 before passing to GTK -void GWorkArea::putClipboard(string const & str) const +void GWorkArea::putClipboard(string const & str) { Glib::RefPtr clipboard = Gtk::Clipboard::get(GDK_SELECTION_PRIMARY); diff --git a/src/frontends/gtk/GWorkArea.h b/src/frontends/gtk/GWorkArea.h index b7f447f11b..eea296c85d 100644 --- a/src/frontends/gtk/GWorkArea.h +++ b/src/frontends/gtk/GWorkArea.h @@ -14,7 +14,7 @@ #include "GPainter.h" -#include "frontends/WorkArea.h" +#include #include #include @@ -55,7 +55,7 @@ private: }; -class GWorkArea : public WorkArea, public sigc::trackable { +class GWorkArea : public sigc::trackable { public: GWorkArea(LyXView & owner, int width, int height); ~GWorkArea(); @@ -80,11 +80,11 @@ public: virtual void setScrollbarParams(int height, int pos, int line_height); /// a selection exists - virtual void haveSelection(bool) const; + virtual void haveSelection(bool); /// virtual std::string const getClipboard() const; /// - virtual void putClipboard(std::string const &) const; + virtual void putClipboard(std::string const &); void inputCommit(gchar * str); private: bool onExpose(GdkEventExpose * event); diff --git a/src/frontends/gtk/GuiClipboard.h b/src/frontends/gtk/GuiClipboard.h new file mode 100644 index 0000000000..f8bff11131 --- /dev/null +++ b/src/frontends/gtk/GuiClipboard.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +/** + * \file gtk/Clipboard.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef CLIPBOARD_H +#define CLIPBOARD_H + +#include "frontends/Clipboard.h" + +#include "GWorkArea.h" + +namespace lyx { +namespace frontend { + +typedef GWorkArea FWorkArea; + +/** + * The GTK version of the Clipboard. + */ +class GuiClipboard: public lyx::frontend::Clipboard +{ +public: + GuiClipboard(FWorkArea * work_area) + : old_work_area_(work_area) + { + } + + virtual ~GuiClipboard() {} + + /** ClipBoard overloaded methods + */ + //@{ + void haveSelection(bool own) + { + old_work_area_->haveSelection(own); + } + + std::string const get() const + { + return old_work_area_->getClipboard(); + } + + void put(std::string const & str) + { + old_work_area_->putClipboard(str); + } + //@} + +private: + FWorkArea * old_work_area_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // CLIPBOARD_H diff --git a/src/frontends/gtk/GuiImplementation.h b/src/frontends/gtk/GuiImplementation.h new file mode 100644 index 0000000000..6f603a66d8 --- /dev/null +++ b/src/frontends/gtk/GuiImplementation.h @@ -0,0 +1,91 @@ +// -*- C++ -*- +/** + * \file gtk/GuiImplementation.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef GUI_IMPLEMENTATION_H +#define GUI_IMPLEMENTATION_H + +#include "frontends/Gui.h" +#include "frontends/LyXView.h" + +#include "GScreen.h" +#include "GWorkArea.h" + +#include "GuiClipboard.h" +#include "GuiWorkArea.h" + +#include + +#include + +namespace lyx { +namespace frontend { + +typedef GScreen FScreen; +typedef GWorkArea FWorkArea; + +/** + * The Gui class is the interface to all GTK components. + */ +class GuiImplementation: public lyx::frontend::Gui +{ +public: + GuiImplementation(LyXView & owner): owner_(owner) + { + } + + virtual ~GuiImplementation() + { + } + + lyx::frontend::Clipboard& clipboard() + { + return *clipboard_; + } + + int newWorkArea(int w, int h) + { + old_work_area_.reset(new FWorkArea(owner_, w, h)); + old_screen_.reset(new FScreen(*old_work_area_.get())); + work_area_.reset(new GuiWorkArea(owner_, w, h, old_screen_.get(), old_work_area_.get())); + clipboard_.reset(new GuiClipboard(old_work_area_.get())); + guiCursor().connect(work_area_.get()); + } + + lyx::frontend::WorkArea& workArea(int id) + { + return *work_area_; + } + + void destroyWorkArea(int id) + { + clipboard_.reset(); + work_area_.reset(); + old_work_area_.reset(); + old_screen_.reset(); + } + +private: + /// + boost::shared_ptr clipboard_; + /// + boost::shared_ptr work_area_; + /// + boost::shared_ptr old_work_area_; + /// + boost::shared_ptr old_screen_; + /// + LyXView & owner_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // GUI_IMPLEMENTATION_H diff --git a/src/frontends/gtk/GuiWorkArea.h b/src/frontends/gtk/GuiWorkArea.h new file mode 100644 index 0000000000..8e6ca041f5 --- /dev/null +++ b/src/frontends/gtk/GuiWorkArea.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +/** + * \file gtk/WorkArea.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef WORKAREA_H +#define WORKAREA_H + +#include "frontends/WorkArea.h" + +#include "GScreen.h" +#include "GWorkArea.h" + +namespace lyx { +namespace frontend { + +typedef GScreen FScreen; +typedef GWorkArea FWorkArea; + +/** + * Temporary wrapper around GWorkArea and GScreen. + * Please refer to the Qt4 implementation for a proper cleanup of the API. + */ +class GuiWorkArea: public lyx::frontend::WorkArea { +public: + GuiWorkArea(LyXView & owner, int w, int h, + FScreen * screen, FWorkArea * work_area) + : lyx::frontend::WorkArea(owner, w, h), + old_screen_(screen), old_work_area_(work_area) + { + } + + ~GuiWorkArea() {} + + /// return the painter object for this work area + virtual lyx::frontend::Painter & getPainter() + { + return old_work_area_->getPainter(); + } + + /// return the width of the work area in pixels + virtual int width() const + { + return old_work_area_->workWidth(); + } + + /// return the height of the work area in pixels + virtual int height() const + { + return old_work_area_->workHeight(); + } + + /** + * Update the scrollbar. + * @param height the total document height in pixels + * @param pos the current position in the document, in pixels + * @param line_height the line-scroll amount, in pixels + */ + virtual void setScrollbarParams(int height, int pos, int line_height) + { + old_work_area_->setScrollbarParams(height, pos, line_height); + } + + + /// paint the cursor and store the background + virtual void showCursor(int x, int y, int h, Cursor_Shape shape) + { + old_screen_->showCursor(x, y, h, shape); + } + + /// hide the cursor + virtual void removeCursor() + { + old_screen_->removeCursor(); + } + +protected: + /// cause the display of the given area of the work area + virtual void expose(int x, int y, int w, int h) + { + old_screen_->expose(x, y, w, h); + } + +private: + FScreen * old_screen_; + FWorkArea * old_work_area_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // WORKAREA_H diff --git a/src/frontends/gtk/LyXScreenFactory.C b/src/frontends/gtk/LyXScreenFactory.C deleted file mode 100644 index 61eb1d9929..0000000000 --- a/src/frontends/gtk/LyXScreenFactory.C +++ /dev/null @@ -1,38 +0,0 @@ -/** - * \file gtk/LyXScreenFactory.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Huang Ying - * - * Full author contact details are available in file CREDITS. - */ - -#include - -// Too hard to make concept checks work with this file -#ifdef _GLIBCXX_CONCEPT_CHECKS -#undef _GLIBCXX_CONCEPT_CHECKS -#endif -#ifdef _GLIBCPP_CONCEPT_CHECKS -#undef _GLIBCPP_CONCEPT_CHECKS -#endif - -#include "GWorkArea.h" -#include "GScreen.h" - -#include "frontends/LyXScreenFactory.h" - -namespace LyXScreenFactory { - - -LyXScreen * create(WorkArea & owner) -{ - using lyx::frontend::GScreen; - using lyx::frontend::GWorkArea; - - return new GScreen(static_cast(owner)); -} - - -} diff --git a/src/frontends/gtk/Makefile.am b/src/frontends/gtk/Makefile.am index b1a708df6e..2ad37f86c5 100644 --- a/src/frontends/gtk/Makefile.am +++ b/src/frontends/gtk/Makefile.am @@ -111,6 +111,8 @@ libgtk_la_SOURCES = \ GToolbar.h \ GUrl.C \ GUrl.h \ + GuiClipboard.h \ + GuiWorkArea.h \ GView.C \ GView.h \ GViewBase.C \ @@ -133,10 +135,9 @@ libgtk_la_SOURCES = \ LyXGdkImage.C \ LyXGdkImage.h \ LyXKeySymFactory.C \ - LyXScreenFactory.C \ - WorkAreaFactory.C \ ghelpers.C \ ghelpers.h \ + GuiImplementation.h \ io_callback.C \ io_callback.h \ lyx_gui.C \ diff --git a/src/frontends/gtk/WorkAreaFactory.C b/src/frontends/gtk/WorkAreaFactory.C deleted file mode 100644 index 18c820747e..0000000000 --- a/src/frontends/gtk/WorkAreaFactory.C +++ /dev/null @@ -1,37 +0,0 @@ -/** - * \file gtk/WorkAreaFactory.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Huang Ying - * - * Full author contact details are available in file CREDITS. - */ - -#include - -// Too hard to make concept checks work with this file -#ifdef _GLIBCXX_CONCEPT_CHECKS -#undef _GLIBCXX_CONCEPT_CHECKS -#endif -#ifdef _GLIBCPP_CONCEPT_CHECKS -#undef _GLIBCPP_CONCEPT_CHECKS -#endif - -#include "GWorkArea.h" - -#include "frontends/WorkAreaFactory.h" - -#include - - -namespace WorkAreaFactory { - - -WorkArea * create(LyXView & owner, int w, int h) -{ - return new lyx::frontend::GWorkArea(owner, w, h); -} - - -} diff --git a/src/frontends/nullpainter.C b/src/frontends/nullpainter.C index 19b2bd286d..085cd82117 100644 --- a/src/frontends/nullpainter.C +++ b/src/frontends/nullpainter.C @@ -18,7 +18,13 @@ #include +namespace lyx { +namespace frontend { + int NullPainter::paperHeight() const { return std::numeric_limits::max(); } + +} // namespace frontend +} // namespace lyx diff --git a/src/frontends/nullpainter.h b/src/frontends/nullpainter.h index 24c33cf6e3..6dc5629d89 100644 --- a/src/frontends/nullpainter.h +++ b/src/frontends/nullpainter.h @@ -15,6 +15,10 @@ #include "LColor.h" #include "Painter.h" + +namespace lyx { +namespace frontend { + class NullPainter : public Painter { public: /// @@ -71,4 +75,7 @@ public: void buttonFrame(int, int, int, int) {} }; +} // namespace frontend +} // namespace lyx + #endif // NULLPAINTER_H diff --git a/src/frontends/qt3/GuiClipboard.h b/src/frontends/qt3/GuiClipboard.h new file mode 100644 index 0000000000..2323f8346c --- /dev/null +++ b/src/frontends/qt3/GuiClipboard.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +/** + * \file qt3/GuiClipboard.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef CLIPBOARD_H +#define CLIPBOARD_H + +#include "frontends/Clipboard.h" + +#include "QWorkArea.h" + +namespace lyx { +namespace frontend { + +typedef QWorkArea FWorkArea; + +/** + * The Qt3 version of the Clipboard. + */ +class GuiClipboard: public lyx::frontend::Clipboard +{ +public: + GuiClipboard(FWorkArea * work_area) + : old_work_area_(work_area) + { + } + + virtual ~GuiClipboard() {} + + /** ClipBoard overloaded methods + */ + //@{ + void haveSelection(bool own) + { + old_work_area_->haveSelection(own); + } + + std::string const get() const + { + return old_work_area_->getClipboard(); + } + + void put(std::string const & str) + { + old_work_area_->putClipboard(str); + } + //@} + +private: + FWorkArea * old_work_area_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // CLIPBOARD_H diff --git a/src/frontends/qt3/GuiImplementation.h b/src/frontends/qt3/GuiImplementation.h new file mode 100644 index 0000000000..199df59f5a --- /dev/null +++ b/src/frontends/qt3/GuiImplementation.h @@ -0,0 +1,89 @@ +// -*- C++ -*- +/** + * \file qt3/Gui.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef GUI_IMPLEMENTATION_H +#define GUI_IMPLEMENTATION_H + +#include "frontends/Gui.h" +#include "frontends/LyXView.h" + +#include "qscreen.h" +#include "QWorkArea.h" + +#include "GuiClipboard.h" +#include "GuiWorkArea.h" + +#include + +namespace lyx { +namespace frontend { + +typedef QScreen FScreen; +typedef QWorkArea FWorkArea; + +/** + * The Gui class is the interface to all Qt3 components. + */ +class GuiImplementation: public lyx::frontend::Gui +{ +public: + GuiImplementation(LyXView & owner): owner_(owner) + { + } + + virtual ~GuiImplementation() + { + } + + lyx::frontend::Clipboard& clipboard() + { + return *clipboard_; + } + + int newWorkArea(int w, int h) + { + old_work_area_.reset(new FWorkArea(owner_, w, h)); + old_screen_.reset(new FScreen(*old_work_area_.get())); + work_area_.reset(new GuiWorkArea(owner_, w, h, old_screen_.get(), old_work_area_.get())); + clipboard_.reset(new GuiClipboard(old_work_area_.get())); + guiCursor().connect(work_area_.get()); + } + + lyx::frontend::WorkArea& workArea(int id) + { + return *work_area_; + } + + void destroyWorkArea(int id) + { + clipboard_.reset(); + work_area_.reset(); + old_work_area_.reset(); + old_screen_.reset(); + } + +private: + /// + boost::shared_ptr clipboard_; + /// + boost::shared_ptr work_area_; + /// + boost::shared_ptr old_work_area_; + /// + boost::shared_ptr old_screen_; + /// + LyXView & owner_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // GUI_IMPLEMENTATION_H diff --git a/src/frontends/qt3/GuiWorkArea.h b/src/frontends/qt3/GuiWorkArea.h new file mode 100644 index 0000000000..bdf3fc8ef5 --- /dev/null +++ b/src/frontends/qt3/GuiWorkArea.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +/** + * \file qt3/WorkArea.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef WORKAREA_H +#define WORKAREA_H + +#include "frontends/WorkArea.h" + +#include "qscreen.h" +#include "QWorkArea.h" + +namespace lyx { +namespace frontend { + +typedef QScreen FScreen; +typedef QWorkArea FWorkArea; + +/** + * Temporary wrapper around QWorkArea and QScreen. + * Please refer to the Qt4 implementation for a proper cleanup of the API. + */ +class GuiWorkArea: public lyx::frontend::WorkArea { +public: + GuiWorkArea(LyXView & owner, int w, int h, + FScreen * screen, FWorkArea * work_area) + : lyx::frontend::WorkArea(owner, w, h), + old_screen_(screen), old_work_area_(work_area) + { + } + + ~GuiWorkArea() {} + + /// return the painter object for this work area + virtual lyx::frontend::Painter & getPainter() + { + return old_work_area_->getPainter(); + } + + /// return the width of the work area in pixels + virtual int width() const + { + return old_work_area_->workWidth(); + } + + /// return the height of the work area in pixels + virtual int height() const + { + return old_work_area_->workHeight(); + } + + /** + * Update the scrollbar. + * @param height the total document height in pixels + * @param pos the current position in the document, in pixels + * @param line_height the line-scroll amount, in pixels + */ + virtual void setScrollbarParams(int height, int pos, int line_height) + { + old_work_area_->setScrollbarParams(height, pos, line_height); + } + + + /// paint the cursor and store the background + virtual void showCursor(int x, int y, int h, Cursor_Shape shape) + { + old_screen_->showCursor(x, y, h, shape); + } + + /// hide the cursor + virtual void removeCursor() + { + old_screen_->removeCursor(); + } + +protected: + /// cause the display of the given area of the work area + virtual void expose(int x, int y, int w, int h) + { + old_screen_->expose(x, y, w, h); + } + +private: + FScreen * old_screen_; + FWorkArea * old_work_area_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // WORKAREA_H diff --git a/src/frontends/qt3/LyXScreenFactory.C b/src/frontends/qt3/LyXScreenFactory.C deleted file mode 100644 index be794ccf5e..0000000000 --- a/src/frontends/qt3/LyXScreenFactory.C +++ /dev/null @@ -1,25 +0,0 @@ -/** - * \file qt3/LyXScreenFactory.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "frontends/LyXScreenFactory.h" - -#include "QWorkArea.h" -#include "qscreen.h" - -namespace LyXScreenFactory { - -LyXScreen * create(WorkArea & owner) -{ - return new QScreen(static_cast(owner)); -} - -} // namespace LyXScreenFactory diff --git a/src/frontends/qt3/Makefile.am b/src/frontends/qt3/Makefile.am index adf2c281ec..abaf567d01 100644 --- a/src/frontends/qt3/Makefile.am +++ b/src/frontends/qt3/Makefile.am @@ -27,8 +27,10 @@ libqt3_la_SOURCES = \ Alert_pimpl.C \ Dialogs.C \ FileDialog.C \ + GuiClipboard.h \ + GuiImplementation.h \ + GuiWorkArea.h \ LyXKeySymFactory.C \ - LyXScreenFactory.C \ QLMenubar.C QLMenubar.h \ qtTimeout.C qtTimeout.h \ QAbout.C QAbout.h \ @@ -73,7 +75,6 @@ libqt3_la_SOURCES = \ QWrap.C QWrap.h \ Qt2BC.C Qt2BC.h \ QtLyXView.h \ - WorkAreaFactory.C \ checkedwidgets.C checkedwidgets.h \ lyx_gui.C \ lcolorcache.h lcolorcache.C \ diff --git a/src/frontends/qt3/QContentPane.C b/src/frontends/qt3/QContentPane.C index fbd9362c94..a9b16162ed 100644 --- a/src/frontends/qt3/QContentPane.C +++ b/src/frontends/qt3/QContentPane.C @@ -78,6 +78,9 @@ mouse_button::state q_motion_state(Qt::ButtonState state) } // namespace anon +namespace lyx { +namespace frontend { + // This is a 'heartbeat' generating synthetic mouse move events when the // cursor is at the top or bottom edge of the viewport. One scroll per 0.2 s SyntheticMouseEvent::SyntheticMouseEvent() @@ -358,3 +361,6 @@ void QContentPane::trackScrollbar(bool track_on) { track_scrollbar_ = track_on; } + +} // namespace frontend +} // namespace lyx diff --git a/src/frontends/qt3/QContentPane.h b/src/frontends/qt3/QContentPane.h index 65a02b7bbe..89a872138b 100644 --- a/src/frontends/qt3/QContentPane.h +++ b/src/frontends/qt3/QContentPane.h @@ -12,12 +12,14 @@ #ifndef QCONTENTPANE_H #define QCONTENTPANE_H +#include "funcrequest.h" #ifdef emit #undef emit -#endif - -#include "funcrequest.h" #include "frontends/Timeout.h" +#define emit +#else +#include "frontends/Timeout.h" +#endif #include #include @@ -31,7 +33,6 @@ #define USE_INPUT_METHODS 1 #endif -class QWorkArea; /// for emulating triple click class double_click { @@ -55,6 +56,11 @@ public: }; +namespace lyx { +namespace frontend { + +class QWorkArea; + /** Qt only emits mouse events when the mouse is being moved, but * we want to generate 'pseudo' mouse events when the mouse button is * pressed and the mouse cursor is below the bottom, or above the top @@ -139,4 +145,7 @@ private: double_click dc_event_; }; +} // namespace frontend +} // namespace lyx + #endif // QCONTENTPANE_H diff --git a/src/frontends/qt3/QLPainter.C b/src/frontends/qt3/QLPainter.C index 2b9f73dbea..4b15ad53d2 100644 --- a/src/frontends/qt3/QLPainter.C +++ b/src/frontends/qt3/QLPainter.C @@ -28,6 +28,8 @@ using std::endl; using std::string; +namespace lyx { +namespace frontend { QLPainter::QLPainter(QWorkArea & qwa) : Painter(), owner_(qwa), paint_check_(0) @@ -248,3 +250,7 @@ void QLPainter::text(int x, int y, char const * s, size_t ls, underline(f, x, y, font_metrics::width(s, ls, f)); } } + +} // namespace frontend +} // namespace lyx + diff --git a/src/frontends/qt3/QLPainter.h b/src/frontends/qt3/QLPainter.h index fbe710fe8e..fad5060cd9 100644 --- a/src/frontends/qt3/QLPainter.h +++ b/src/frontends/qt3/QLPainter.h @@ -12,19 +12,24 @@ #ifndef QLPAINTER_H #define QLPAINTER_H -#include "Painter.h" +#include "frontends/Painter.h" #include + class LyXFont; -class QWorkArea; class QPainter; class QString; +namespace lyx { +namespace frontend { + +class QWorkArea; + /** * QLPainter - a painter implementation for Xlib */ -class QLPainter : public Painter { +class QLPainter : public lyx::frontend::Painter { public: QLPainter(QWorkArea &); @@ -133,4 +138,7 @@ private: int paint_check_; }; +} // namespace frontend +} // namespace lyx + #endif // QLPAINTER_H diff --git a/src/frontends/qt3/QWorkArea.C b/src/frontends/qt3/QWorkArea.C index 3a00893a17..b16075f7e2 100644 --- a/src/frontends/qt3/QWorkArea.C +++ b/src/frontends/qt3/QWorkArea.C @@ -38,22 +38,24 @@ #include #endif -#ifdef Q_OS_MAC #include -using lyx::support::subst; -#endif +using lyx::support::internalLineEnding; +using lyx::support::externalLineEnding; using std::endl; using std::string; namespace os = lyx::support::os; namespace { -QWorkArea * wa_ptr = 0; +lyx::frontend::QWorkArea * wa_ptr = 0; } +namespace lyx { +namespace frontend { + QWorkArea::QWorkArea(LyXView & owner, int, int) - : WorkArea(), QWidget(qApp->mainWidget()), owner_(owner), painter_(*this) + : QWidget(qApp->mainWidget()), owner_(owner), painter_(*this) { scrollbar_ = new QScrollBar(QScrollBar::Vertical, this); content_ = new QContentPane(this); @@ -99,6 +101,10 @@ void QWorkArea::setScrollbarParams(int h, int pos, int line_h) scrollbar_->setPageStep(height()); } +} // namespace frontend +} // namespace lyx + + #ifdef Q_WS_X11 bool lyxX11EventFilter(XEvent * xev) { @@ -184,7 +190,11 @@ pascal OSErr handleOpenDocuments(const AppleEvent* inEvent, } #endif // Q_WS_MACX -void QWorkArea::haveSelection(bool own) const + +namespace lyx { +namespace frontend { + +void QWorkArea::haveSelection(bool own) { wa_ptr = const_cast(this); @@ -206,24 +216,14 @@ string const QWorkArea::getClipboard() const QString str = QApplication::clipboard()->text(); if (str.isNull()) return string(); -#ifdef Q_OS_MAC - // The MAC clipboard uses \r for lineendings, and we use \n - return subst(fromqstr(str), '\r', '\n'); -#else - return fromqstr(str); -#endif + return internalLineEnding(fromqstr(str)); } -void QWorkArea::putClipboard(string const & str) const +void QWorkArea::putClipboard(string const & str) { QApplication::clipboard()->setSelectionMode(true); -#ifdef Q_OS_MAC - // The MAC clipboard uses \r for lineendings, and we use \n - QApplication::clipboard()->setText(toqstr(subst(str, '\n', '\r'))); -#else - QApplication::clipboard()->setText(toqstr(str)); -#endif + QApplication::clipboard()->setText(toqstr(externalLineEnding(str))); } @@ -247,3 +247,6 @@ void QWorkArea::dropEvent(QDropEvent * event) } } } + +} // namespace frontend +} // namespace lyx diff --git a/src/frontends/qt3/QWorkArea.h b/src/frontends/qt3/QWorkArea.h index caaada90c2..84affb9429 100644 --- a/src/frontends/qt3/QWorkArea.h +++ b/src/frontends/qt3/QWorkArea.h @@ -13,7 +13,6 @@ #ifndef QWORKAREA_H #define QWORKAREA_H -#include "WorkArea.h" #include "QLPainter.h" #include "QContentPane.h" @@ -23,6 +22,9 @@ class LyXView; class QPixmap; class QWidget; +namespace lyx { +namespace frontend { + /** * Qt-specific implementation of the work area @@ -31,7 +33,7 @@ class QWidget; * It consists of a content pane widget, and a scrollbar. * Hopefully soon we can just use QScrollView ... */ -class QWorkArea : public WorkArea, public QWidget { +class QWorkArea : public QWidget { public: friend class QContentPane; @@ -39,7 +41,7 @@ public: virtual ~QWorkArea(); /// return this widget's painter - virtual Painter & getPainter() { return painter_; } + virtual lyx::frontend::Painter & getPainter() { return painter_; } /// return the width of the content pane virtual int workWidth() const { return content_->width(); } /// return the height of the content pane @@ -48,11 +50,11 @@ public: virtual void setScrollbarParams(int height, int pos, int line_height); /// a selection exists - virtual void haveSelection(bool) const; + virtual void haveSelection(bool); /// virtual std::string const getClipboard() const; /// - virtual void putClipboard(std::string const &) const; + virtual void putClipboard(std::string const &); /// virtual void dragEnterEvent(QDragEnterEvent * event); /// @@ -81,4 +83,8 @@ private: QLPainter painter_; }; + +} // namespace frontend +} // namespace lyx + #endif // QWORKAREA_H diff --git a/src/frontends/qt3/QtView.C b/src/frontends/qt3/QtView.C index 503cfb440c..1e1bab5540 100644 --- a/src/frontends/qt3/QtView.C +++ b/src/frontends/qt3/QtView.C @@ -56,7 +56,7 @@ int const statusbar_timer_value = 3000; QtView::QtView(unsigned int width, unsigned int height) - : QMainWindow(), LyXView(), commandbuffer_(0) + : QMainWindow(), LyXView(), commandbuffer_(0), frontend_(*this) { resize(width, height); diff --git a/src/frontends/qt3/QtView.h b/src/frontends/qt3/QtView.h index 35737fa475..29cf568f5d 100644 --- a/src/frontends/qt3/QtView.h +++ b/src/frontends/qt3/QtView.h @@ -18,6 +18,8 @@ #include "frontends/LyXView.h" +#include "GuiImplementation.h" + #include #include @@ -62,6 +64,9 @@ public: // returns true if this view has the focus. virtual bool hasFocus() const; + // + lyx::frontend::Gui & gui() { return frontend_; } + public slots: /// idle timeout void update_view_state_qt(); @@ -86,6 +91,9 @@ private: /// command buffer QCommandBuffer * commandbuffer_; + + /// + GuiImplementation frontend_; }; } // namespace frontend diff --git a/src/frontends/qt3/WorkAreaFactory.C b/src/frontends/qt3/WorkAreaFactory.C deleted file mode 100644 index 054fee2b29..0000000000 --- a/src/frontends/qt3/WorkAreaFactory.C +++ /dev/null @@ -1,23 +0,0 @@ -/** - * \file qt3/WorkAreaFactory.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "frontends/WorkAreaFactory.h" -#include "QWorkArea.h" - -namespace WorkAreaFactory { - -WorkArea * create(LyXView & owner, int w, int h) -{ - return new QWorkArea(owner, w, h); -} - -} // namespace WorkAreaFactory diff --git a/src/frontends/qt3/qscreen.C b/src/frontends/qt3/qscreen.C index 5b5ab545dc..ba4cf89dea 100644 --- a/src/frontends/qt3/qscreen.C +++ b/src/frontends/qt3/qscreen.C @@ -30,9 +30,11 @@ void copyInPixmap(QPixmap * p, int dest_y, int src_y, int src_w, int src_h) } // namespace anon +namespace lyx { +namespace frontend { QScreen::QScreen(QWorkArea & o) - : LyXScreen(), owner_(o) + : owner_(o) { } @@ -42,12 +44,6 @@ QScreen::~QScreen() } -WorkArea & QScreen::workarea() -{ - return owner_; -} - - void QScreen::repaint() { QWidget * content = owner_.getContent(); @@ -162,3 +158,7 @@ void QScreen::removeCursor() owner_.getContent() ->update(cursor_x_, cursor_y_, cursor_w_, cursor_h_); } + + +} // namespace frontend +} // namespace lyx diff --git a/src/frontends/qt3/qscreen.h b/src/frontends/qt3/qscreen.h index 7d595f5e45..fed647d2e8 100644 --- a/src/frontends/qt3/qscreen.h +++ b/src/frontends/qt3/qscreen.h @@ -12,27 +12,27 @@ #ifndef QSCREEN_H #define QSCREEN_H -#include "screen.h" +#include "frontends/GuiCursor.h" + #include #include +namespace lyx { +namespace frontend { + class QWorkArea; -class WorkArea; /** * Qt implementation of toolkit-specific parts of LyXScreen. */ -class QScreen : public LyXScreen { +class QScreen { public: QScreen(QWorkArea &); virtual ~QScreen(); -protected: - /// get the work area - virtual WorkArea & workarea(); - +public: /// repaint the whole content immediately void repaint(); @@ -40,7 +40,7 @@ protected: virtual void expose(int x, int y, int exp_width, int exp_height); /// paint the cursor and store the background - virtual void showCursor(int x, int y, int h, Cursor_Shape shape); + virtual void showCursor(int x, int y, int h, lyx::frontend::Cursor_Shape shape); /// hide the cursor virtual void removeCursor(); @@ -63,4 +63,7 @@ private: QColor cursor_color_; }; +} // namespace frontend +} // namespace lyx + #endif // QSCREEN_H diff --git a/src/frontends/qt3/qtTimeout.C b/src/frontends/qt3/qtTimeout.C index 241932b4a0..61f8e70beb 100644 --- a/src/frontends/qt3/qtTimeout.C +++ b/src/frontends/qt3/qtTimeout.C @@ -14,6 +14,9 @@ #include "debug.h" +// stupid Qt +#undef emit + Timeout::Timeout(unsigned int msec, Type t) : pimpl_(new qtTimeout(*this)), type(t), timeout_ms(msec) diff --git a/src/frontends/qt3/qtTimeout.h b/src/frontends/qt3/qtTimeout.h index 6fa3ad2a8c..51ea8ff44f 100644 --- a/src/frontends/qt3/qtTimeout.h +++ b/src/frontends/qt3/qtTimeout.h @@ -12,11 +12,15 @@ #ifndef QTTIMEOUT_H #define QTTIMEOUT_H +#ifdef emit +#undef emit +#include "frontends/Timeout.h" +#define emit +#else #include "frontends/Timeout.h" +#endif #include -// stupid Qt -#undef emit /** * This class executes the callback when the timeout expires diff --git a/src/frontends/qt4/GuiClipboard.h b/src/frontends/qt4/GuiClipboard.h new file mode 100644 index 0000000000..cce918c9f0 --- /dev/null +++ b/src/frontends/qt4/GuiClipboard.h @@ -0,0 +1,44 @@ +// -*- C++ -*- +/** + * \file GuiClipboard.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author unknown + * \author John Levon + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef CLIPBOARD_H +#define CLIPBOARD_H + +#include "frontends/Clipboard.h" + +namespace lyx { +namespace frontend { + +/** + * The Qt4 version of the Clipboard. + */ +class GuiClipboard: public Clipboard +{ +public: + GuiClipboard() {} + + virtual ~GuiClipboard() {} + + /** ClipBoard overloaded methods + */ + //@{ + void haveSelection(bool own); + std::string const get() const; + void put(std::string const & str); + //@} +}; + +} // namespace frontend +} // namespace lyx + +#endif // CLIPBOARD_H diff --git a/src/frontends/qt4/GuiImplementation.C b/src/frontends/qt4/GuiImplementation.C new file mode 100644 index 0000000000..18c13b5c1c --- /dev/null +++ b/src/frontends/qt4/GuiImplementation.C @@ -0,0 +1,57 @@ +// -*- C++ -*- +/** + * \file GuiImplementation.C + * 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. + */ + +#include "GuiImplementation.h" +#include "GuiWorkArea.h" +#include "QtView.h" + +using boost::shared_ptr; + +namespace lyx { +namespace frontend { + +GuiImplementation::GuiImplementation(QtView & owner): owner_(owner), max_id_(0) +{ +} + + +Clipboard& GuiImplementation::clipboard() +{ + return clipboard_; +} + + +int GuiImplementation::newWorkArea(int w, int h) +{ + size_t const id = max_id_; + ++max_id_; + work_areas_[id].reset(new GuiWorkArea(owner_, w, h)); + return id; +} + +WorkArea& GuiImplementation::workArea(int id) +{ + BOOST_ASSERT(work_areas_.find(id) != work_areas_.end()); + + guiCursor().connect(work_areas_[id].get()); + + return *work_areas_[id].get(); +} + + +void GuiImplementation::destroyWorkArea(int id) +{ + work_areas_.erase(id); +} + +} // namespace frontend +} // namespace lyx diff --git a/src/frontends/qt4/GuiImplementation.h b/src/frontends/qt4/GuiImplementation.h new file mode 100644 index 0000000000..31f23ad873 --- /dev/null +++ b/src/frontends/qt4/GuiImplementation.h @@ -0,0 +1,58 @@ +// -*- C++ -*- +/** + * \file GuiImplementation.h + * 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. + */ + +#ifndef GUI_IMPLEMENTATION_H +#define GUI_IMPLEMENTATION_H + +#include "frontends/Gui.h" +#include "GuiClipboard.h" + +#include + +#include + +namespace lyx { +namespace frontend { + +class GuiWorkArea; +class QtView; + +/** + * The GuiImplementation class is the interface to all Qt4 components. + */ +class GuiImplementation: public Gui +{ +public: + GuiImplementation(QtView & owner); + virtual ~GuiImplementation() {} + + Clipboard& clipboard(); + + int newWorkArea(int w, int h); + WorkArea& workArea(int id); + void destroyWorkArea(int id); + +private: + /// + GuiClipboard clipboard_; + /// + std::map > work_areas_; + /// + QtView & owner_; + /// + size_t max_id_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // GUI_IMPLEMENTATION_H diff --git a/src/frontends/qt4/GuiWorkArea.C b/src/frontends/qt4/GuiWorkArea.C new file mode 100644 index 0000000000..76c8c3b5f5 --- /dev/null +++ b/src/frontends/qt4/GuiWorkArea.C @@ -0,0 +1,610 @@ +/** + * \file GuiWorkArea.C + * 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. + */ + +#include + +#include + +#include "GuiWorkArea.h" +#include "QLPainter.h" +#include "QLyXKeySym.h" +#include "QtView.h" + +#include "ColorCache.h" +#include "qt_helpers.h" +#include "Application.h" +#include "BufferView.h" +#include "debug.h" +#include "funcrequest.h" +#include "LColor.h" +#include "support/os.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// Abdel (09/06/2006): +// I want the drawing to be fast without Keyboard buffering so when working +// on optimization, please set the following macro to 0: +#define USE_KEY_BUFFERING 0 + +using std::endl; +using std::string; + +namespace os = lyx::support::os; + +namespace { + +/// return the LyX key state from Qt's +key_modifier::state q_key_state(Qt::ButtonState state) +{ + key_modifier::state k = key_modifier::none; + if (state & Qt::ControlModifier) + k |= key_modifier::ctrl; + if (state & Qt::ShiftModifier) + k |= key_modifier::shift; + if (state & Qt::AltModifier) + k |= key_modifier::alt; + return k; +} + + +/// return the LyX mouse button state from Qt's +mouse_button::state q_button_state(Qt::ButtonState button) +{ + mouse_button::state b = mouse_button::none; + switch (button) { + case Qt::LeftButton: + b = mouse_button::button1; + break; + case Qt::MidButton: + b = mouse_button::button2; + break; + case Qt::RightButton: + b = mouse_button::button3; + break; + default: + break; + } + return b; +} + + +/// return the LyX mouse button state from Qt's +mouse_button::state q_motion_state(Qt::ButtonState state) +{ + mouse_button::state b = mouse_button::none; + if (state & Qt::LeftButton) + b |= mouse_button::button1; + if (state & Qt::MidButton) + b |= mouse_button::button2; + if (state & Qt::RightButton) + b |= mouse_button::button3; + return b; +} + +} // namespace anon + +namespace lyx { +namespace frontend { + +// This is a 'heartbeat' generating synthetic mouse move events when the +// cursor is at the top or bottom edge of the viewport. One scroll per 0.2 s +SyntheticMouseEvent::SyntheticMouseEvent() + : timeout(200), restart_timeout(true), + x_old(-1), y_old(-1), scrollbar_value_old(-1.0) +{} + + +GuiWorkArea::GuiWorkArea(LyXView & owner, int w, int h) +: QAbstractScrollArea(QtView::mainWidget()), WorkArea(owner, w, h), view_(owner), painter_(this) +{ + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + QtView::mainWidget()->setCentralWidget(this); + + setAcceptDrops(true); + + setMinimumSize(100, 70); + + viewport()->setAutoFillBackground(false); + viewport()->setAttribute(Qt::WA_OpaquePaintEvent); + + viewport()->setFocusPolicy(Qt::WheelFocus); + viewport()->setFocus(); + setFocusPolicy(Qt::WheelFocus); + + viewport()->setCursor(Qt::IBeamCursor); + + resize(w, h); + show(); + workWidth_ = w; + workHeight_ = h; + + synthetic_mouse_event_.timeout.timeout.connect( + boost::bind(&GuiWorkArea::generateSyntheticMouseEvent, + this)); + + // Initialize the vertical Scroll Bar + QObject::connect(verticalScrollBar(), SIGNAL(actionTriggered(int)), + this, SLOT(adjustViewWithScrollBar(int))); + + // PageStep only depends on the viewport height. + verticalScrollBar()->setPageStep(workHeight_); + + lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION + << "\n Area width\t" << width() + << "\n Area height\t" << height() + << "\n viewport width\t" << viewport()->width() + << "\n viewport height\t" << viewport()->height() + << endl; + + if (USE_KEY_BUFFERING) { + // This is the keyboard buffering stuff... + // I don't see any need for this under windows. The keyboard is reactive + // enough... + + if ( !QObject::connect(&step_timer_, SIGNAL(timeout()), + this, SLOT(keyeventTimeout())) ) + lyxerr[Debug::GUI] << "ERROR: keyeventTimeout cannot connect!" << endl; + + // Start the timer, one-shot. + step_timer_.start(50, true); + } + + /////////////////////////////////////////////////////////////////////// + // Specific stuff goes here... + +#if USE_INPUT_METHODS + // to make qt-immodule work + setInputMethodEnabled(true); +#endif + +} + +GuiWorkArea::~GuiWorkArea() +{ +} + +void GuiWorkArea::setScrollbarParams(int h, int scroll_pos, int scroll_line_step) +{ + // do what cursor movement does (some grey) + h += height() / 4; + int scroll_max_ = std::max(0, h - height()); + + verticalScrollBar()->setRange(0, scroll_max_); + verticalScrollBar()->setSliderPosition(scroll_pos); + verticalScrollBar()->setLineStep(scroll_line_step); +} + +void GuiWorkArea::adjustViewWithScrollBar(int) +{ + /* + lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION + << " verticalScrollBar val=" << verticalScrollBar()->value() + << " verticalScrollBar pos=" << verticalScrollBar()->sliderPosition() + << " min=" << verticalScrollBar()->minimum() + << " max=" << verticalScrollBar()->maximum() + << " pagestep=" << verticalScrollBar()->pageStep() + << " linestep=" << verticalScrollBar()->lineStep() + << endl; + */ + view_.view()->scrollDocView(verticalScrollBar()->sliderPosition()); +} + + +void GuiWorkArea::dragEnterEvent(QDragEnterEvent * event) +{ + if (event->mimeData()->hasUrls()) + event->accept(); + /// \todo Ask lyx-devel is this is enough: + /// if (event->mimeData()->hasFormat("text/plain")) + /// event->acceptProposedAction(); +} + + +void GuiWorkArea::dropEvent(QDropEvent* event) +{ + QList files = event->mimeData()->urls(); + if (files.isEmpty()) + return; + + lyxerr[Debug::GUI] << "GuiWorkArea::dropEvent: got URIs!" << endl; + for (int i = 0; i!=files.size(); ++i) { + string const file = os::internal_path(fromqstr(files.at(i).toString())); + if (!file.empty()) + view_.view()->workAreaDispatch(FuncRequest(LFUN_FILE_OPEN, file)); + } +} + + +void GuiWorkArea::mousePressEvent(QMouseEvent * e) +{ + if (dc_event_.active && dc_event_ == *e) { + dc_event_.active = false; + FuncRequest cmd(LFUN_MOUSE_TRIPLE, + dc_event_.x, dc_event_.y, + q_button_state(dc_event_.state)); + view_.view()->workAreaDispatch(cmd); + return; + } + + FuncRequest const cmd(LFUN_MOUSE_PRESS, e->x(), e->y(), + q_button_state(e->button())); + view_.view()->workAreaDispatch(cmd); +} + + +void GuiWorkArea::mouseReleaseEvent(QMouseEvent * e) +{ + if (synthetic_mouse_event_.timeout.running()) + synthetic_mouse_event_.timeout.stop(); + + FuncRequest const cmd(LFUN_MOUSE_RELEASE, e->x(), e->y(), + q_button_state(e->button())); + view_.view()->workAreaDispatch(cmd); +} + + +void GuiWorkArea::mouseMoveEvent(QMouseEvent * e) +{ + FuncRequest cmd(LFUN_MOUSE_MOTION, e->x(), e->y(), + q_motion_state(e->state())); + + // If we're above or below the work area... + if (e->y() <= 20 || e->y() >= viewport()->height() - 20) { + // Make sure only a synthetic event can cause a page scroll, + // so they come at a steady rate: + if (e->y() <= 20) + // _Force_ a scroll up: + cmd.y = -40; + else + cmd.y = viewport()->height(); + // Store the event, to be handled when the timeout expires. + synthetic_mouse_event_.cmd = cmd; + + if (synthetic_mouse_event_.timeout.running()) + // Discard the event. Note that it _may_ be handled + // when the timeout expires if + // synthetic_mouse_event_.cmd has not been overwritten. + // Ie, when the timeout expires, we handle the + // most recent event but discard all others that + // occurred after the one used to start the timeout + // in the first place. + return; + else { + synthetic_mouse_event_.restart_timeout = true; + synthetic_mouse_event_.timeout.start(); + // Fall through to handle this event... + } + + } else if (synthetic_mouse_event_.timeout.running()) { + // Store the event, to be possibly handled when the timeout + // expires. + // Once the timeout has expired, normal control is returned + // to mouseMoveEvent (restart_timeout = false). + // This results in a much smoother 'feel' when moving the + // mouse back into the work area. + synthetic_mouse_event_.cmd = cmd; + synthetic_mouse_event_.restart_timeout = false; + return; + } + + // Has anything changed on-screen since the last QMouseEvent + // was received? + double const scrollbar_value = verticalScrollBar()->value(); + if (e->x() != synthetic_mouse_event_.x_old || + e->y() != synthetic_mouse_event_.y_old || + scrollbar_value != synthetic_mouse_event_.scrollbar_value_old) { + // Yes it has. Store the params used to check this. + synthetic_mouse_event_.x_old = e->x(); + synthetic_mouse_event_.y_old = e->y(); + synthetic_mouse_event_.scrollbar_value_old = scrollbar_value; + + // ... and dispatch the event to the LyX core. + view_.view()->workAreaDispatch(cmd); + } +} + + +void GuiWorkArea::wheelEvent(QWheelEvent * e) +{ + // Wheel rotation by one notch results in a delta() of 120 (see + // documentation of QWheelEvent) + int const lines = qApp->wheelScrollLines() * e->delta() / 120; + verticalScrollBar()->setValue(verticalScrollBar()->value() - + lines * verticalScrollBar()->lineStep()); + adjustViewWithScrollBar(); +} + + +void GuiWorkArea::generateSyntheticMouseEvent() +{ + // Set things off to generate the _next_ 'pseudo' event. + if (synthetic_mouse_event_.restart_timeout) + synthetic_mouse_event_.timeout.start(); + + // Has anything changed on-screen since the last timeout signal + // was received? + double const scrollbar_value = verticalScrollBar()->value(); + if (scrollbar_value != synthetic_mouse_event_.scrollbar_value_old) { + // Yes it has. Store the params used to check this. + synthetic_mouse_event_.scrollbar_value_old = scrollbar_value; + + // ... and dispatch the event to the LyX core. + view_.view()->workAreaDispatch(synthetic_mouse_event_.cmd); + } +} + + +void GuiWorkArea::keyPressEvent(QKeyEvent * e) +{ + lyxerr[Debug::KEY] << BOOST_CURRENT_FUNCTION + << " count=" << e->count() + << " text=" << (const char *) e->text() + << " isAutoRepeat=" << e->isAutoRepeat() + << " key=" << e->key() + << endl; + + if (USE_KEY_BUFFERING) { + keyeventQueue_.push(boost::shared_ptr(new QKeyEvent(*e))); + } + else { + boost::shared_ptr sym(new QLyXKeySym); + sym->set(e); + view_.view()->workAreaKeyPress(sym, q_key_state(e->state())); + } +} + +// This is used only if USE_KEY_BUFFERING is defined... +void GuiWorkArea::keyeventTimeout() +{ + bool handle_autos = true; + + while (!keyeventQueue_.empty()) { + boost::shared_ptr ev = keyeventQueue_.front(); + + // We never handle more than one auto repeated + // char in a list of queued up events. + if (!handle_autos && ev->isAutoRepeat()) { + keyeventQueue_.pop(); + continue; + } + + boost::shared_ptr sym(new QLyXKeySym); + sym->set(ev.get()); + + lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION + << " count=" << ev->count() + << " text=" << (const char *) ev->text() + << " isAutoRepeat=" << ev->isAutoRepeat() + << " key=" << ev->key() + << endl; + + view_.view()->workAreaKeyPress(sym, q_key_state(ev->state())); + keyeventQueue_.pop(); + + handle_autos = false; + } + + // Restart the timer. + step_timer_.start(25, true); +} + + +void GuiWorkArea::mouseDoubleClickEvent(QMouseEvent * e) +{ + dc_event_ = double_click(e); + + if (!dc_event_.active) + return; + + dc_event_.active = false; + + FuncRequest cmd(LFUN_MOUSE_DOUBLE, + dc_event_.x, dc_event_.y, + q_button_state(dc_event_.state)); + view_.view()->workAreaDispatch(cmd); +} + + +void GuiWorkArea::resizeEvent(QResizeEvent *) +{ + workWidth_ = viewport()->width(); + workHeight_ = viewport()->height(); + + verticalScrollBar()->setPageStep(viewport()->height()); + +// screen_device_ = QPixmap(viewport()->width(), viewport()->height()); +// paint_device_ = QImage(viewport()->width(), viewport()->height(), QImage::Format_RGB32); + paint_device_ = QPixmap(viewport()->width(), viewport()->height()); + + view_.view()->workAreaResize(); + + /* + lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION + << "\n QWidget width\t" << this->QWidget::width() + << "\n QWidget height\t" << this->QWidget::height() + << "\n viewport width\t" << viewport()->width() + << "\n viewport height\t" << viewport()->height() + << "\n QResizeEvent rect left\t" << rect().left() + << "\n QResizeEvent rect right\t" << rect().right() + << endl; + */ +} + + +void GuiWorkArea::update(int x, int y, int w, int h) +{ + //screen_device_.fromImage(paint_device_); + //QPainter q(&screen_device_); + //q.drawImage(x, y, paint_device_.copy(x, y, w, h)); + + viewport()->update(x, y, w, h); +} + + +void GuiWorkArea::paintEvent(QPaintEvent * e) +{ + /* + lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION + << "\n QWidget width\t" << this->width() + << "\n QWidget height\t" << this->height() + << "\n viewport width\t" << viewport()->width() + << "\n viewport height\t" << viewport()->height() + << "\n pixmap width\t" << pixmap_->width() + << "\n pixmap height\t" << pixmap_->height() + << "\n QPaintEvent x\t" << e->rect().x() + << "\n QPaintEvent y\t" << e->rect().y() + << "\n QPaintEvent w\t" << e->rect().width() + << "\n QPaintEvent h\t" << e->rect().height() + << endl; + */ + QPainter q(viewport()); + q.drawPixmap(e->rect(), paint_device_, e->rect()); + + if (show_vcursor_) + q.drawPixmap(cursor_x_, cursor_y_, vcursor_); + + if (show_hcursor_) + q.drawPixmap(cursor_x_, cursor_y_ + cursor_h_ - 1, hcursor_); +} + + +QPixmap GuiWorkArea::copyScreen(int x, int y, int w, int h) const +{ + return paint_device_.copy(x, y, w, h); +} + + +void GuiWorkArea::drawScreen(int x, int y, QPixmap pixmap) +{ + QPainter q(&paint_device_); + q.drawPixmap(x, y, pixmap); + viewport()->update(x, y, pixmap.width(), pixmap.height()); +} + + +void GuiWorkArea::expose(int x, int y, int w, int h) +{ +// lyxerr[Debug::GUI] << "expose " << w << 'x' << h +// << '+' << x << '+' << y << std::endl; + + update(x, y, w, h); +} + + +void GuiWorkArea::showCursor(int x, int y, int h, Cursor_Shape shape) +{ + if (!qApp->focusWidget()) + return; + + show_vcursor_ = true; + + QColor const & required_color = lcolorcache.get(LColor::cursor); + + if (x==cursor_x_ && y==cursor_y_ && h==cursor_h_ + && cursor_color_ == required_color + && cursor_shape_ == shape) { + show_hcursor_ = lshape_cursor_; + viewport()->update(cursor_x_, cursor_y_, cursor_w_, cursor_h_); + return; + } + + // Cache the dimensions of the cursor. + cursor_x_ = x; + cursor_y_ = y; + cursor_h_ = h; + cursor_color_ = required_color; + cursor_shape_ = shape; + + switch (cursor_shape_) { + case BAR_SHAPE: + // FIXME the cursor width shouldn't be hard-coded! + cursor_w_ = 2; + lshape_cursor_ = false; + break; + case L_SHAPE: + cursor_w_ = cursor_h_ / 3; + lshape_cursor_ = true; + break; + case REVERSED_L_SHAPE: + cursor_w_ = cursor_h_ / 3; + cursor_x_ -= cursor_w_ - 1; + lshape_cursor_ = true; + break; + } + + // We cache two pixmaps: + // 1 the vertical line of the cursor. + // 2 the horizontal line of the L-shaped cursor (if necessary). + + // Draw the new (vertical) cursor. + vcursor_ = QPixmap(cursor_w_, cursor_h_); + vcursor_.fill(cursor_color_); + + // Draw the new (horizontal) cursor if necessary. + if (lshape_cursor_) { + hcursor_ = QPixmap(cursor_w_, 1); + hcursor_.fill(cursor_color_); + show_hcursor_ = true; + } + + viewport()->update(cursor_x_, cursor_y_, cursor_w_, cursor_h_); +} + + +void GuiWorkArea::removeCursor() +{ + show_vcursor_ = false; + show_hcursor_ = false; + + viewport()->update(cursor_x_, cursor_y_, cursor_w_, cursor_h_); +} + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +// Specific stuff + +//////////////////////////////////////////////////////////////////////// +// qt-immodule specific stuff goes here... + +#if USE_INPUT_METHODS +// to make qt-immodule work + +void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e) +{ + QString const text = e->text(); + if (!text.isEmpty()) { + int key = 0; + // needed to make math superscript work on some systems + // ideally, such special coding should not be necessary + if (text == "^") + key = Qt::Key_AsciiCircum; + QKeyEvent ev(QEvent::KeyPress, key, *text.ascii(), 0, text); + keyPressEvent(&ev); + } + e->accept(); +} +#endif + +} // namespace frontend +} // namespace lyx + +#include "GuiWorkArea_moc.cpp" diff --git a/src/frontends/qt4/GuiWorkArea.h b/src/frontends/qt4/GuiWorkArea.h new file mode 100644 index 0000000000..9a041c00cc --- /dev/null +++ b/src/frontends/qt4/GuiWorkArea.h @@ -0,0 +1,253 @@ +// -*- C++ -*- +/** + * \file GuiWorkArea.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author unknown + * \author John Levon + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef WORKAREA_H +#define WORKAREA_H + +#if (defined(Q_WS_X11) && QT_VERSION >= 0x030200) +#define USE_INPUT_METHODS 1 +#endif + +#ifdef emit +#undef emit +#endif + +#include "frontends/LyXView.h" +#include "frontends/WorkArea.h" + +#include "QLPainter.h" + +#include "funcrequest.h" +#include "frontends/Timeout.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class Painter; + +class QWidget; +class QDragEnterEvent; +class QDropEvent; +class QMouseEvent; + +namespace lyx { +namespace frontend { + +/// for emulating triple click +class double_click { +public: + int x; + int y; + Qt::ButtonState state; + bool active; + + bool operator==(QMouseEvent const & e) { + return x == e.x() && y == e.y() + && state == e.button(); + } + + double_click() + : x(0), y(0), state(Qt::NoButton), active(false) {} + + double_click(QMouseEvent * e) + : x(e->x()), y(e->y()), + state(e->button()), active(true) {} +}; + +/** Qt only emits mouse events when the mouse is being moved, but + * we want to generate 'pseudo' mouse events when the mouse button is + * pressed and the mouse cursor is below the bottom, or above the top + * of the work area. In this way, we'll be able to continue scrolling + * (and selecting) the text. + * + * This class stores all the parameters needed to make this happen. + */ +class SyntheticMouseEvent +{ +public: + SyntheticMouseEvent(); + + FuncRequest cmd; + Timeout timeout; + bool restart_timeout; + int x_old; + int y_old; + double scrollbar_value_old; +}; + +/** + * Qt-specific implementation of the work area + * (buffer view GUI) +*/ +class GuiWorkArea: public QAbstractScrollArea, public WorkArea { + + Q_OBJECT + +public: + + GuiWorkArea(LyXView & owner, int w, int h); + + virtual ~GuiWorkArea(); + /// return the width of the content pane + virtual int width() const { return workWidth_; } + + /// return the height of the content pane + virtual int height() const { return workHeight_; } + /// + virtual void setScrollbarParams(int height, int pos, int line_height); + + /// + virtual void dragEnterEvent(QDragEnterEvent * event); + + /// + virtual void dropEvent(QDropEvent* event); + + /// return the widget's painter + virtual Painter & getPainter() { return (Painter &) painter_; } + + /// return the backing pixmap + QPaintDevice * paintDevice() { return &paint_device_; } + + /// update the passed area. + void update(int x, int y, int w, int h); + + /// return a screen copy of the defined area. + QPixmap copyScreen(int x, int y, int w, int h) const; + + /// Draw a pixmap onto the backing pixmap. + /** + QPixmap is implicitely shared so no need to pass by reference. + */ + void drawScreen(int x, int y, QPixmap pixmap); + + LyXView & view() { return view_; } + + /// copies specified area of pixmap to screen + virtual void expose(int x, int y, int exp_width, int exp_height); + + /// paint the cursor and store the background + virtual void showCursor(int x, int y, int h, Cursor_Shape shape); + + /// hide the cursor + virtual void removeCursor(); + +protected: + + /// repaint part of the widget + void paintEvent(QPaintEvent * e); + /// widget has been resized + void resizeEvent(QResizeEvent * e); + /// mouse button press + void mousePressEvent(QMouseEvent * e); + /// mouse button release + void mouseReleaseEvent(QMouseEvent * e); + /// mouse double click of button + void mouseDoubleClickEvent(QMouseEvent * e); + /// mouse motion + void mouseMoveEvent(QMouseEvent * e); + /// wheel event + void wheelEvent(QWheelEvent * e); + /// key press + void keyPressEvent(QKeyEvent * e); + +#if USE_INPUT_METHODS +protected: + /// IM events + void inputMethodEvent(QInputMethodEvent * e); +#endif + +public slots: + + /// Timeout event Slot for keyboard bufferring. + /// \todo This is not used currently in the code, remove? + void keyeventTimeout(); + + /// 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); + +private: + /// + LyXView & view_; + + /// Buffer view width. + int workWidth_; + + /// Buffer view height. + int workHeight_; + + /// Our painter. + QLPainter painter_; + + /// The slot connected to SyntheticMouseEvent::timeout. + void generateSyntheticMouseEvent(); + + /// + SyntheticMouseEvent synthetic_mouse_event_; + + /// Our client side painting device. + //QImage paint_device_; + QPixmap paint_device_; + + /// Our server side painting device. + //QPixmap screen_device_; + + /// \todo remove + QTimer step_timer_; + + /// \todo remove + std::queue > keyeventQueue_; + + double_click dc_event_; + + /// + int cursor_x_; + /// + int cursor_y_; + /// + int cursor_w_; + /// + int cursor_h_; + /// + QPixmap hcursor_; + /// + QPixmap vcursor_; + /// + bool show_hcursor_; + /// + bool show_vcursor_; + /// + bool lshape_cursor_; + /// + QColor cursor_color_; + /// + Cursor_Shape cursor_shape_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // WORKAREA_H diff --git a/src/frontends/qt4/LyXScreenFactory.C b/src/frontends/qt4/LyXScreenFactory.C deleted file mode 100644 index e1a4c3d44c..0000000000 --- a/src/frontends/qt4/LyXScreenFactory.C +++ /dev/null @@ -1,24 +0,0 @@ -/** - * \file qt4/LyXScreenFactory.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "frontends/LyXScreenFactory.h" - -#include "QWorkArea.h" - -namespace LyXScreenFactory { - -LyXScreen * create(WorkArea & owner) -{ - return &(static_cast(owner)); -} - -} // namespace LyXScreenFactory diff --git a/src/frontends/qt4/Makefile.am b/src/frontends/qt4/Makefile.am index 851f0ebe80..bbe92e62c5 100644 --- a/src/frontends/qt4/Makefile.am +++ b/src/frontends/qt4/Makefile.am @@ -30,17 +30,16 @@ AM_CPPFLAGS += \ -I$(top_srcdir)/src/frontends/controllers libqt4_la_SOURCES = \ - QDialogView.C \ - QDialogView.h \ - Action.C Action.h \ Alert_pimpl.C \ + Application.C Application.h \ ColorCache.h ColorCache.C \ Dialogs.C \ FileDialog.C \ + FontLoader.h FontLoader.C \ + GuiClipboard.h GuiClipboard.C \ + GuiImplementation.h GuiImplementation.C \ LyXKeySymFactory.C \ - LyXScreenFactory.C \ QLMenubar.C QLMenubar.h \ - qtTimeout.C qtTimeout.h \ QAbout.C QAbout.h \ QBibitem.C QBibitem.h \ QBibtex.C QBibtex.h \ @@ -51,6 +50,7 @@ libqt4_la_SOURCES = \ QCharacter.C QCharacter.h \ QCitation.C QCitation.h \ QDocument.C QDocument.h \ + QDialogView.C QDialogView.h \ QErrorList.C QErrorList.h \ QERT.C QERT.h \ QExternal.C QExternal.h \ @@ -80,16 +80,14 @@ libqt4_la_SOURCES = \ QToc.C QToc.h \ QURL.C QURL.h \ QVSpace.C QVSpace.h \ - QWorkArea.C QWorkArea.h \ QWrap.C QWrap.h \ Qt2BC.C Qt2BC.h \ - WorkAreaFactory.C \ checkedwidgets.C checkedwidgets.h \ lyx_gui.C \ panelstack.h panelstack.C \ qfontexample.h qfontexample.C \ - FontLoader.h FontLoader.C \ qfont_metrics.C \ qlkey.h \ qt_helpers.h qt_helpers.C \ + qtTimeout.C qtTimeout.h \ $(MOCFILES) diff --git a/src/frontends/qt4/Makefile.dialogs b/src/frontends/qt4/Makefile.dialogs index 558351c2d5..4a4d85dc73 100644 --- a/src/frontends/qt4/Makefile.dialogs +++ b/src/frontends/qt4/Makefile.dialogs @@ -78,6 +78,7 @@ MOCFILES = \ emptytable.C emptytable.h \ FileDialog_private.C FileDialog_private.h \ floatplacement.C floatplacement.h \ + GuiWorkArea.C GuiWorkArea.h \ iconpalette.C iconpalette.h \ InsertTableWidget.C InsertTableWidget.h \ lengthcombo.C lengthcombo.h \ @@ -129,7 +130,6 @@ MOCFILES = \ QtView.C QtView.h \ QURLDialog.C QURLDialog.h \ QVSpaceDialog.C QVSpaceDialog.h \ - QWorkArea.C QWorkArea.h \ QWrapDialog.C QWrapDialog.h \ QLToolbar.C QLToolbar.h \ socket_callback.C socket_callback.h \ diff --git a/src/frontends/qt4/QLPainter.C b/src/frontends/qt4/QLPainter.C index ad0f4d66d4..f54a74537b 100644 --- a/src/frontends/qt4/QLPainter.C +++ b/src/frontends/qt4/QLPainter.C @@ -13,7 +13,7 @@ #include "QLPainter.h" -#include "QWorkArea.h" +#include "GuiWorkArea.h" #include "QLImage.h" #include "ColorCache.h" @@ -33,12 +33,14 @@ using std::endl; using std::string; +namespace lyx { +namespace frontend { QLPainter::~QLPainter() { } -QLPainter::QLPainter(QWorkArea * qwa) +QLPainter::QLPainter(GuiWorkArea * qwa) : Painter(), qwa_(qwa) { } @@ -234,7 +236,7 @@ void QLPainter::text(int x, int y, char const * s, size_t ls, QString str; str.setLength(ls); - for (int i = 0; i < ls; ++i) + for (size_t i = 0; i < ls; ++i) str[i] = QChar(encoding->ucs(s[i])); // HACK: QT3 refuses to show single compose characters @@ -248,7 +250,7 @@ void QLPainter::text(int x, int y, char const * s, size_t ls, qp.setFont(fontloader.get(f)); // We need to draw the text as LTR as we use our own bidi code. qp.setLayoutDirection(Qt::LeftToRight); - qp.drawText(x, y, str, -1); + qp.drawText(x, y, str); } else { smallCapsText(x, y, str, f); } @@ -270,3 +272,7 @@ void QLPainter::drawImage(int x, int y, QImage const & image) QPainter qp(qwa_->paintDevice()); qp.drawImage(x, y, image); } + +} // namespace frontend +} // namespace lyx + diff --git a/src/frontends/qt4/QLPainter.h b/src/frontends/qt4/QLPainter.h index 93e048f644..88e8c4096f 100644 --- a/src/frontends/qt4/QLPainter.h +++ b/src/frontends/qt4/QLPainter.h @@ -23,14 +23,18 @@ class QPainter; class QString; class QPixmap; class QImage; -class QWorkArea; + +namespace lyx { +namespace frontend { + +class GuiWorkArea; /** * QLPainter - a painter implementation for Qt4 */ class QLPainter : public Painter { public: - QLPainter(QWorkArea *); + QLPainter(GuiWorkArea *); ~QLPainter(); @@ -146,11 +150,14 @@ private: boost::scoped_ptr qp_; /// the working area - QWorkArea * qwa_; + GuiWorkArea * qwa_; LColor::color current_color_; Painter::line_style current_ls_; Painter::line_width current_lw_; }; +} // namespace frontend +} // namespace lyx + #endif // QLPAINTER_H diff --git a/src/frontends/qt4/QWorkArea.C b/src/frontends/qt4/QWorkArea.C deleted file mode 100644 index 6de2dd4066..0000000000 --- a/src/frontends/qt4/QWorkArea.C +++ /dev/null @@ -1,770 +0,0 @@ -/** - * \file QWorkArea.C - * 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. - */ - -#include - -#include - -#include "QWorkArea.h" -#include "QLPainter.h" -#include "QLyXKeySym.h" -#include "QtView.h" - -#include "ColorCache.h" -#include "qt_helpers.h" -#include "BufferView.h" -#include "debug.h" -#include "funcrequest.h" -#include "LColor.h" -#include "support/os.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/////////////////////////////////////////////////////////////// -// Specific stuff -#ifdef Q_WS_X11 -#include -#endif - -#ifdef Q_WS_MACX -#include -#include -using lyx::support::subst; -#endif - -// You can find other qt-immodule, X11 and MACX specific stuff -// at the end of this file... -/////////////////////////////////////////////////////////////// - -using std::endl; -using std::string; - -namespace os = lyx::support::os; - -namespace { - -QWorkArea * wa_ptr = 0; - -/// return the LyX key state from Qt's -key_modifier::state q_key_state(Qt::ButtonState state) -{ - key_modifier::state k = key_modifier::none; - if (state & Qt::ControlModifier) - k |= key_modifier::ctrl; - if (state & Qt::ShiftModifier) - k |= key_modifier::shift; - if (state & Qt::AltModifier) - k |= key_modifier::alt; - return k; -} - - -/// return the LyX mouse button state from Qt's -mouse_button::state q_button_state(Qt::ButtonState button) -{ - mouse_button::state b = mouse_button::none; - switch (button) { - case Qt::LeftButton: - b = mouse_button::button1; - break; - case Qt::MidButton: - b = mouse_button::button2; - break; - case Qt::RightButton: - b = mouse_button::button3; - break; - default: - break; - } - return b; -} - - -/// return the LyX mouse button state from Qt's -mouse_button::state q_motion_state(Qt::ButtonState state) -{ - mouse_button::state b = mouse_button::none; - if (state & Qt::LeftButton) - b |= mouse_button::button1; - if (state & Qt::MidButton) - b |= mouse_button::button2; - if (state & Qt::RightButton) - b |= mouse_button::button3; - return b; -} - -} // namespace anon - -// This is a 'heartbeat' generating synthetic mouse move events when the -// cursor is at the top or bottom edge of the viewport. One scroll per 0.2 s -SyntheticMouseEvent::SyntheticMouseEvent() - : timeout(200), restart_timeout(true), - x_old(-1), y_old(-1), scrollbar_value_old(-1.0) -{} - - -QWorkArea::QWorkArea(LyXView & owner, int w, int h) - : QAbstractScrollArea(lyx::frontend::QtView::mainWidget()), WorkArea(), view_(owner), painter_(this) -{ - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - lyx::frontend::QtView::mainWidget()->setCentralWidget(this); - - setAcceptDrops(true); - - setMinimumSize(100, 70); - - viewport()->setAutoFillBackground(false); - viewport()->setAttribute(Qt::WA_OpaquePaintEvent); - - viewport()->setFocusPolicy(Qt::WheelFocus); - viewport()->setFocus(); - setFocusPolicy(Qt::WheelFocus); - - viewport()->setCursor(Qt::IBeamCursor); - - resize(w, h); - show(); - workWidth_ = w; - workHeight_ = h; - - synthetic_mouse_event_.timeout.timeout.connect( - boost::bind(&QWorkArea::generateSyntheticMouseEvent, - this)); - - // Initialize the vertical Scroll Bar - QObject::connect(verticalScrollBar(), SIGNAL(actionTriggered(int)), - this, SLOT(adjustViewWithScrollBar(int))); - - // PageStep only depends on the viewport height. - verticalScrollBar()->setPageStep(workHeight_); - - lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION - << "\n Area width\t" << width() - << "\n Area height\t" << height() - << "\n viewport width\t" << viewport()->width() - << "\n viewport height\t" << viewport()->height() - << endl; - -/* - // This is the keyboard buffering stuff... - // I don't see any need for this under windows. The keyboard is reactive - // enough... - - if ( !QObject::connect(&step_timer_, SIGNAL(timeout()), - this, SLOT(keyeventTimeout())) ) - lyxerr[Debug::GUI] << "ERROR: keyeventTimeout cannot connect!" << endl; - - // Start the timer, one-shot. - step_timer_.start(50, true); -*/ - - /////////////////////////////////////////////////////////////////////// - // Specific stuff goes here... - -#if USE_INPUT_METHODS - // to make qt-immodule work - setInputMethodEnabled(true); -#endif - -#ifdef Q_WS_X11 - // doubleClickInterval() is 400 ms on X11 witch is just too long. - // On Windows and Mac OS X, the operating system's value is used. - // On Microsoft Windows, calling this function sets the double - // click interval for all applications. So we don't! - QApplication::setDoubleClickInterval(300); -#endif - -#ifdef Q_WS_MACX - wa_ptr = this; -#endif -} - -QWorkArea::~QWorkArea() -{ -} - -void QWorkArea::setScrollbarParams(int h, int scroll_pos, int scroll_line_step) -{ - // do what cursor movement does (some grey) - h += height() / 4; - int scroll_max_ = std::max(0, h - height()); - - verticalScrollBar()->setRange(0, scroll_max_); - verticalScrollBar()->setSliderPosition(scroll_pos); - verticalScrollBar()->setLineStep(scroll_line_step); -} - -void QWorkArea::adjustViewWithScrollBar(int action) -{ - /* - lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION - << " verticalScrollBar val=" << verticalScrollBar()->value() - << " verticalScrollBar pos=" << verticalScrollBar()->sliderPosition() - << " min=" << verticalScrollBar()->minimum() - << " max=" << verticalScrollBar()->maximum() - << " pagestep=" << verticalScrollBar()->pageStep() - << " linestep=" << verticalScrollBar()->lineStep() - << endl; - */ - view_.view()->scrollDocView(verticalScrollBar()->sliderPosition()); -} - - -void QWorkArea::haveSelection(bool own) const -{ - /// \todo ask X11 and MAC devels why this wa_ptr is useful. - wa_ptr = const_cast(this); - - if (!QApplication::clipboard()->supportsSelection()) - return; - - if (own) { - QApplication::clipboard()->setText(QString(), QClipboard::Selection); - } - // We don't need to do anything if own = false, as this case is - // handled by QT. -} - - -string const QWorkArea::getClipboard() const -{ - QString str = QApplication::clipboard()->text(QClipboard::Selection); - lyxerr[Debug::ACTION] << "getClipboard: " << (const char*) str << endl; - if (str.isNull()) - return string(); -#ifdef Q_WS_MACX - // The MAC clipboard uses \r for lineendings, and we use \n - return subst(fromqstr(str), '\r', '\n'); -#else - return fromqstr(str); -#endif -} - - -void QWorkArea::putClipboard(string const & str) const -{ -#ifdef Q_WS_MACX - // The MAC clipboard uses \r for lineendings, and we use \n - QApplication::clipboard()->setText(toqstr(subst(str, '\n', '\r')), - QClipboard::Selection); -#else - QApplication::clipboard()->setText(toqstr(str), QClipboard::Selection); -#endif - lyxerr[Debug::ACTION] << "putClipboard: " << str << endl; -} - - -void QWorkArea::dragEnterEvent(QDragEnterEvent * event) -{ - if (event->mimeData()->hasUrls()) - event->accept(); - /// \todo Ask lyx-devel is this is enough: - /// if (event->mimeData()->hasFormat("text/plain")) - /// event->acceptProposedAction(); - -} - - -void QWorkArea::dropEvent(QDropEvent* event) -{ - QList files = event->mimeData()->urls(); - if (files.isEmpty()) - return; - - lyxerr[Debug::GUI] << "QWorkArea::dropEvent: got URIs!" << endl; - for (int i = 0; i!=files.size(); ++i) { - string const file = os::internal_path(fromqstr(files.at(i).toString())); - if (!file.empty()) - view_.view()->workAreaDispatch(FuncRequest(LFUN_FILE_OPEN, file)); - } -} - - -void QWorkArea::mousePressEvent(QMouseEvent * e) -{ - if (dc_event_.active && dc_event_ == *e) { - dc_event_.active = false; - FuncRequest cmd(LFUN_MOUSE_TRIPLE, - dc_event_.x, dc_event_.y, - q_button_state(dc_event_.state)); - view_.view()->workAreaDispatch(cmd); - return; - } - - FuncRequest const cmd(LFUN_MOUSE_PRESS, e->x(), e->y(), - q_button_state(e->button())); - view_.view()->workAreaDispatch(cmd); -} - - -void QWorkArea::mouseReleaseEvent(QMouseEvent * e) -{ - if (synthetic_mouse_event_.timeout.running()) - synthetic_mouse_event_.timeout.stop(); - - FuncRequest const cmd(LFUN_MOUSE_RELEASE, e->x(), e->y(), - q_button_state(e->button())); - view_.view()->workAreaDispatch(cmd); -} - - -void QWorkArea::mouseMoveEvent(QMouseEvent * e) -{ - FuncRequest cmd(LFUN_MOUSE_MOTION, e->x(), e->y(), - q_motion_state(e->state())); - - // If we're above or below the work area... - if (e->y() <= 20 || e->y() >= viewport()->height() - 20) { - // Make sure only a synthetic event can cause a page scroll, - // so they come at a steady rate: - if (e->y() <= 20) - // _Force_ a scroll up: - cmd.y = -40; - else - cmd.y = viewport()->height(); - // Store the event, to be handled when the timeout expires. - synthetic_mouse_event_.cmd = cmd; - - if (synthetic_mouse_event_.timeout.running()) - // Discard the event. Note that it _may_ be handled - // when the timeout expires if - // synthetic_mouse_event_.cmd has not been overwritten. - // Ie, when the timeout expires, we handle the - // most recent event but discard all others that - // occurred after the one used to start the timeout - // in the first place. - return; - else { - synthetic_mouse_event_.restart_timeout = true; - synthetic_mouse_event_.timeout.start(); - // Fall through to handle this event... - } - - } else if (synthetic_mouse_event_.timeout.running()) { - // Store the event, to be possibly handled when the timeout - // expires. - // Once the timeout has expired, normal control is returned - // to mouseMoveEvent (restart_timeout = false). - // This results in a much smoother 'feel' when moving the - // mouse back into the work area. - synthetic_mouse_event_.cmd = cmd; - synthetic_mouse_event_.restart_timeout = false; - return; - } - - // Has anything changed on-screen since the last QMouseEvent - // was received? - double const scrollbar_value = verticalScrollBar()->value(); - if (e->x() != synthetic_mouse_event_.x_old || - e->y() != synthetic_mouse_event_.y_old || - scrollbar_value != synthetic_mouse_event_.scrollbar_value_old) { - // Yes it has. Store the params used to check this. - synthetic_mouse_event_.x_old = e->x(); - synthetic_mouse_event_.y_old = e->y(); - synthetic_mouse_event_.scrollbar_value_old = scrollbar_value; - - // ... and dispatch the event to the LyX core. - view_.view()->workAreaDispatch(cmd); - } -} - - -void QWorkArea::wheelEvent(QWheelEvent * e) -{ - // Wheel rotation by one notch results in a delta() of 120 (see - // documentation of QWheelEvent) - int const lines = QApplication::wheelScrollLines() * e->delta() / 120; - verticalScrollBar()->setValue(verticalScrollBar()->value() - - lines * verticalScrollBar()->lineStep()); - adjustViewWithScrollBar(); -} - - -void QWorkArea::generateSyntheticMouseEvent() -{ - // Set things off to generate the _next_ 'pseudo' event. - if (synthetic_mouse_event_.restart_timeout) - synthetic_mouse_event_.timeout.start(); - - // Has anything changed on-screen since the last timeout signal - // was received? - double const scrollbar_value = verticalScrollBar()->value(); - if (scrollbar_value != synthetic_mouse_event_.scrollbar_value_old) { - // Yes it has. Store the params used to check this. - synthetic_mouse_event_.scrollbar_value_old = scrollbar_value; - - // ... and dispatch the event to the LyX core. - view_.view()->workAreaDispatch(synthetic_mouse_event_.cmd); - } -} - -void QWorkArea::keyPressEvent(QKeyEvent * e) -{ - lyxerr[Debug::KEY] << BOOST_CURRENT_FUNCTION - << " count=" << e->count() - << " text=" << (const char *) e->text() - << " isAutoRepeat=" << e->isAutoRepeat() - << " key=" << e->key() - << endl; - -// keyeventQueue_.push(boost::shared_ptr(new QKeyEvent(*e))); - - boost::shared_ptr sym(new QLyXKeySym); - sym->set(e); - view_.view()->workAreaKeyPress(sym, q_key_state(e->state())); - -} - -// This is not used for now... -void QWorkArea::keyeventTimeout() -{ - bool handle_autos = true; - - while (!keyeventQueue_.empty()) { - boost::shared_ptr ev = keyeventQueue_.front(); - - // We never handle more than one auto repeated - // char in a list of queued up events. - if (!handle_autos && ev->isAutoRepeat()) { - keyeventQueue_.pop(); - continue; - } - - boost::shared_ptr sym(new QLyXKeySym); - sym->set(ev.get()); - - lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION - << " count=" << ev->count() - << " text=" << (const char *) ev->text() - << " isAutoRepeat=" << ev->isAutoRepeat() - << " key=" << ev->key() - << endl; - - view_.view()->workAreaKeyPress(sym, q_key_state(ev->state())); - keyeventQueue_.pop(); - - handle_autos = false; - } - - // Restart the timer. - step_timer_.start(25, true); -} - - -void QWorkArea::mouseDoubleClickEvent(QMouseEvent * e) -{ - dc_event_ = double_click(e); - - if (!dc_event_.active) - return; - - dc_event_.active = false; - - FuncRequest cmd(LFUN_MOUSE_DOUBLE, - dc_event_.x, dc_event_.y, - q_button_state(dc_event_.state)); - view_.view()->workAreaDispatch(cmd); -} - - -void QWorkArea::resizeEvent(QResizeEvent * resizeEvent) -{ - workWidth_ = viewport()->width(); - workHeight_ = viewport()->height(); - - verticalScrollBar()->setPageStep(viewport()->height()); - -// screen_device_ = QPixmap(viewport()->width(), viewport()->height()); -// paint_device_ = QImage(viewport()->width(), viewport()->height(), QImage::Format_RGB32); - paint_device_ = QPixmap(viewport()->width(), viewport()->height()); - - view_.view()->workAreaResize(); - - /* - lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION - << "\n QWidget width\t" << this->QWidget::width() - << "\n QWidget height\t" << this->QWidget::height() - << "\n viewport width\t" << viewport()->width() - << "\n viewport height\t" << viewport()->height() - << "\n QResizeEvent rect left\t" << rect().left() - << "\n QResizeEvent rect right\t" << rect().right() - << endl; - */ -} - -void QWorkArea::update(int x, int y, int w, int h) -{ - //screen_device_.fromImage(paint_device_); - //QPainter q(&screen_device_); - //q.drawImage(x, y, paint_device_.copy(x, y, w, h)); - - viewport()->update(x, y, w, h); -} - -void QWorkArea::paintEvent(QPaintEvent * e) -{ - /* - lyxerr[Debug::GUI] << BOOST_CURRENT_FUNCTION - << "\n QWidget width\t" << this->width() - << "\n QWidget height\t" << this->height() - << "\n viewport width\t" << viewport()->width() - << "\n viewport height\t" << viewport()->height() - << "\n pixmap width\t" << pixmap_->width() - << "\n pixmap height\t" << pixmap_->height() - << "\n QPaintEvent x\t" << e->rect().x() - << "\n QPaintEvent y\t" << e->rect().y() - << "\n QPaintEvent w\t" << e->rect().width() - << "\n QPaintEvent h\t" << e->rect().height() - << endl; - */ - QPainter q(viewport()); - q.drawPixmap(e->rect(), paint_device_, e->rect()); - - if (show_vcursor_) - q.drawPixmap(cursor_x_, cursor_y_, vcursor_); - - if (show_hcursor_) - q.drawPixmap(cursor_x_, cursor_y_ + cursor_h_ - 1, hcursor_); -} - - -QPixmap QWorkArea::copyScreen(int x, int y, int w, int h) const -{ - return paint_device_.copy(x, y, w, h); -} - -void QWorkArea::drawScreen(int x, int y, QPixmap pixmap) -{ - QPainter q(&paint_device_); - q.drawPixmap(x, y, pixmap); - viewport()->update(x, y, pixmap.width(), pixmap.height()); -} - -/////////////////////////////////////////////////////////////// -// LyXSreen overloaded methods: - -WorkArea & QWorkArea::workarea() -{ -// return static_cast (*this); - return *this; -} - - -void QWorkArea::expose(int x, int y, int w, int h) -{ -// lyxerr[Debug::GUI] << "expose " << w << 'x' << h -// << '+' << x << '+' << y << std::endl; - - update(x, y, w, h); -} - - -void QWorkArea::showCursor(int x, int y, int h, Cursor_Shape shape) -{ - if (!qApp->focusWidget()) - return; - - show_vcursor_ = true; - - QColor const & required_color = lcolorcache.get(LColor::cursor); - - if (x==cursor_x_ && y==cursor_y_ && h==cursor_h_ - && cursor_color_ == required_color - && cursor_shape_ == shape) { - show_hcursor_ = lshape_cursor_; - viewport()->update(cursor_x_, cursor_y_, cursor_w_, cursor_h_); - return; - } - - // Cache the dimensions of the cursor. - cursor_x_ = x; - cursor_y_ = y; - cursor_h_ = h; - cursor_color_ = required_color; - cursor_shape_ = shape; - - switch (cursor_shape_) { - case BAR_SHAPE: - // FIXME the cursor width shouldn't be hard-coded! - cursor_w_ = 2; - lshape_cursor_ = false; - break; - case L_SHAPE: - cursor_w_ = cursor_h_ / 3; - lshape_cursor_ = true; - break; - case REVERSED_L_SHAPE: - cursor_w_ = cursor_h_ / 3; - cursor_x_ -= cursor_w_ - 1; - lshape_cursor_ = true; - break; - } - - // We cache two pixmaps: - // 1 the vertical line of the cursor. - // 2 the horizontal line of the L-shaped cursor (if necessary). - - // Draw the new (vertical) cursor. - vcursor_ = QPixmap(cursor_w_, cursor_h_); - vcursor_.fill(cursor_color_); - - // Draw the new (horizontal) cursor if necessary. - if (lshape_cursor_) { - hcursor_ = QPixmap(cursor_w_, 1); - hcursor_.fill(cursor_color_); - show_hcursor_ = true; - } - - viewport()->update(cursor_x_, cursor_y_, cursor_w_, cursor_h_); -} - - -void QWorkArea::removeCursor() -{ - show_vcursor_ = false; - show_hcursor_ = false; - - viewport()->update(cursor_x_, cursor_y_, cursor_w_, cursor_h_); -} - -/////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////// -// Specific stuff - -//////////////////////////////////////////////////////////////////////// -// qt-immodule specific stuff goes here... - -#if USE_INPUT_METHODS -// to make qt-immodule work - -void QWorkArea::inputMethodEvent(QInputMethodEvent * e) -{ - QString const text = e->text(); - if (!text.isEmpty()) { - int key = 0; - // needed to make math superscript work on some systems - // ideally, such special coding should not be necessary - if (text == "^") - key = Qt::Key_AsciiCircum; - QKeyEvent ev(QEvent::KeyPress, key, *text.ascii(), 0, text); - keyPressEvent(&ev); - } - e->accept(); -} -#endif - - -//////////////////////////////////////////////////////////////////////// -// X11 specific stuff goes here... - -#ifdef Q_WS_X11 -bool lyxX11EventFilter(XEvent * xev) -{ - switch (xev->type) { - case SelectionRequest: - lyxerr[Debug::GUI] << "X requested selection." << endl; - if (wa_ptr) - wa_ptr->view().view()->selectionRequested(); - break; - case SelectionClear: - lyxerr[Debug::GUI] << "Lost selection." << endl; - if (wa_ptr) - wa_ptr->view().view()->selectionLost(); - break; - } - return false; -} -#endif - - -//////////////////////////////////////////////////////////////////////// -// Mac OSX specific stuff goes here... - -#ifdef Q_WS_MACX -namespace{ -OSErr checkAppleEventForMissingParams(const AppleEvent& theAppleEvent) - { - DescType returnedType; - Size actualSize; - OSErr err = AEGetAttributePtr(&theAppleEvent, keyMissedKeywordAttr, - typeWildCard, &returnedType, nil, 0, - &actualSize); - switch (err) { - case errAEDescNotFound: - return noErr; - case noErr: - return errAEEventNotHandled; - default: - return err; - } - } -} - -pascal OSErr handleOpenDocuments(const AppleEvent* inEvent, - AppleEvent* /*reply*/, long /*refCon*/) -{ - QString s_arg; - AEDescList documentList; - OSErr err = AEGetParamDesc(inEvent, keyDirectObject, typeAEList, - &documentList); - if (err != noErr) - return err; - - err = checkAppleEventForMissingParams(*inEvent); - if (err == noErr) { - long documentCount; - err = AECountItems(&documentList, &documentCount); - for (long documentIndex = 1; - err == noErr && documentIndex <= documentCount; - documentIndex++) { - DescType returnedType; - Size actualSize; - AEKeyword keyword; - FSRef ref; - char qstr_buf[1024]; - err = AESizeOfNthItem(&documentList, documentIndex, - &returnedType, &actualSize); - if (err == noErr) { - err = AEGetNthPtr(&documentList, documentIndex, - typeFSRef, &keyword, - &returnedType, (Ptr)&ref, - sizeof(FSRef), &actualSize); - if (err == noErr) { - FSRefMakePath(&ref, (UInt8*)qstr_buf, - 1024); - s_arg=QString::fromUtf8(qstr_buf); - wa_ptr->view().view()->workAreaDispatch( - FuncRequest(LFUN_FILE_OPEN, - fromqstr(s_arg))); - break; - } - } - } // for ... - } - AEDisposeDesc(&documentList); - return err; -} -#endif // Q_WS_MACX - -#include "QWorkArea_moc.cpp" diff --git a/src/frontends/qt4/QWorkArea.h b/src/frontends/qt4/QWorkArea.h deleted file mode 100644 index 1f5147ee21..0000000000 --- a/src/frontends/qt4/QWorkArea.h +++ /dev/null @@ -1,262 +0,0 @@ -// -*- C++ -*- -/** - * \file QWorkArea.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author unknown - * \author John Levon - * \author Abdelrazak Younes - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef QWORKAREA_H -#define QWORKAREA_H - -#if (defined(Q_WS_X11) && QT_VERSION >= 0x030200) -#define USE_INPUT_METHODS 1 -#endif - -#ifdef emit -#undef emit -#endif - -#include "WorkArea.h" -#include "QLPainter.h" -#include "LyXView.h" -#include "screen.h" - -#include "funcrequest.h" -#include "frontends/Timeout.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -class Painter; - -class QWidget; -class QDragEnterEvent; -class QDropEvent; -class QMouseEvent; - -/// for emulating triple click -class double_click { -public: - int x; - int y; - Qt::ButtonState state; - bool active; - - bool operator==(QMouseEvent const & e) { - return x == e.x() && y == e.y() - && state == e.button(); - } - - double_click() - : x(0), y(0), state(Qt::NoButton), active(false) {} - - double_click(QMouseEvent * e) - : x(e->x()), y(e->y()), - state(e->button()), active(true) {} -}; - - -/** Qt only emits mouse events when the mouse is being moved, but - * we want to generate 'pseudo' mouse events when the mouse button is - * pressed and the mouse cursor is below the bottom, or above the top - * of the work area. In this way, we'll be able to continue scrolling - * (and selecting) the text. - * - * This class stores all the parameters needed to make this happen. - */ -class SyntheticMouseEvent -{ -public: - SyntheticMouseEvent(); - - FuncRequest cmd; - Timeout timeout; - bool restart_timeout; - int x_old; - int y_old; - double scrollbar_value_old; -}; - -/** - * Qt-specific implementation of the work area - * (buffer view GUI) -*/ -class QWorkArea : public QAbstractScrollArea, public WorkArea, public LyXScreen { - - Q_OBJECT - -public: - - QWorkArea(LyXView & owner, int w, int h); - - virtual ~QWorkArea(); - /// return the width of the content pane - virtual int workWidth() const { return workWidth_; } - - /// return the height of the content pane - virtual int workHeight() const { return workHeight_; } - /// - virtual void setScrollbarParams(int height, int pos, int line_height); - - /// a selection exists - virtual void haveSelection(bool) const; - - /// - virtual std::string const getClipboard() const; - - /// - virtual void putClipboard(std::string const &) const; - - /// - virtual void dragEnterEvent(QDragEnterEvent * event); - - /// - virtual void dropEvent(QDropEvent* event); - - /// return the widget's painter - virtual Painter & getPainter() { return (Painter &) painter_; } - - /// return the backing pixmap - QPaintDevice * paintDevice() { return &paint_device_; } - - /// update the passed area. - void update(int x, int y, int w, int h); - - /// return a screen copy of the defined area. - QPixmap copyScreen(int x, int y, int w, int h) const; - - /// Draw a pixmap onto the backing pixmap. - /** - QPixmap is implicitely shared so no need to pass by reference. - */ - void drawScreen(int x, int y, QPixmap pixmap); - - LyXView & view() { return view_; } - - // LyXScreen overloaded methods: - - /// get the work area - virtual WorkArea & workarea(); - - /// copies specified area of pixmap to screen - virtual void expose(int x, int y, int exp_width, int exp_height); - - /// paint the cursor and store the background - virtual void showCursor(int x, int y, int h, Cursor_Shape shape); - - /// hide the cursor - virtual void removeCursor(); - -protected: - - /// repaint part of the widget - void paintEvent(QPaintEvent * e); - /// widget has been resized - void resizeEvent(QResizeEvent * e); - /// mouse button press - void mousePressEvent(QMouseEvent * e); - /// mouse button release - void mouseReleaseEvent(QMouseEvent * e); - /// mouse double click of button - void mouseDoubleClickEvent(QMouseEvent * e); - /// mouse motion - void mouseMoveEvent(QMouseEvent * e); - /// wheel event - void wheelEvent(QWheelEvent * e); - /// key press - void keyPressEvent(QKeyEvent * e); - -#if USE_INPUT_METHODS -protected: - /// IM events - void QWorkArea::inputMethodEvent(QInputMethodEvent * e) -#endif - -public slots: - - /// Timeout event Slot for keyboard bufferring. - /// \todo This is not used currently in the code, remove? - void keyeventTimeout(); - - /// 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); - -private: - /// - LyXView & view_; - - /// Buffer view width. - int workWidth_; - - /// Buffer view height. - int workHeight_; - - /// Our painter. - QLPainter painter_; - - /// The slot connected to SyntheticMouseEvent::timeout. - void generateSyntheticMouseEvent(); - - /// - SyntheticMouseEvent synthetic_mouse_event_; - - /// Our client side painting device. - //QImage paint_device_; - QPixmap paint_device_; - - /// Our server side painting device. - //QPixmap screen_device_; - - /// \todo remove - QTimer step_timer_; - - /// \todo remove - std::queue > keyeventQueue_; - - double_click dc_event_; - - /// - int cursor_x_; - /// - int cursor_y_; - /// - int cursor_w_; - /// - int cursor_h_; - /// - QPixmap hcursor_; - /// - QPixmap vcursor_; - /// - bool show_hcursor_; - /// - bool show_vcursor_; - /// - bool lshape_cursor_; - /// - QColor cursor_color_; - /// - Cursor_Shape cursor_shape_; -}; - -#endif // QWORKAREA_H diff --git a/src/frontends/qt4/QtView.C b/src/frontends/qt4/QtView.C index afcb82cee9..db07c73f22 100644 --- a/src/frontends/qt4/QtView.C +++ b/src/frontends/qt4/QtView.C @@ -3,7 +3,7 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * \author John Levon * \author Abdelrazak Younes * @@ -71,7 +71,7 @@ int const statusbar_timer_value = 3000; QtView::QtView(unsigned int width, unsigned int height) - : QMainWindow(), LyXView(), commandbuffer_(0) + : QMainWindow(), LyXView(), commandbuffer_(0), frontend_(*this) { mainWidget_ = this; diff --git a/src/frontends/qt4/QtView.h b/src/frontends/qt4/QtView.h index 937629dd7e..ab18f8cf66 100644 --- a/src/frontends/qt4/QtView.h +++ b/src/frontends/qt4/QtView.h @@ -17,6 +17,8 @@ // Must be here because of moc. #include +#include "GuiImplementation.h" + #include "frontends/LyXView.h" #include "funcrequest.h" @@ -72,6 +74,9 @@ public: // returns true if this view has the focus. virtual bool hasFocus() const; + // + Gui & gui() { return frontend_; } + static QMainWindow* mainWidget(); public slots: @@ -105,6 +110,8 @@ private: /// static QMainWindow* mainWidget_; + + GuiImplementation frontend_; }; } // namespace frontend diff --git a/src/frontends/qt4/WorkAreaFactory.C b/src/frontends/qt4/WorkAreaFactory.C deleted file mode 100644 index 39748da0d1..0000000000 --- a/src/frontends/qt4/WorkAreaFactory.C +++ /dev/null @@ -1,23 +0,0 @@ -/** - * \file qt4/WorkAreaFactory.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "frontends/WorkAreaFactory.h" -#include "QWorkArea.h" - -namespace WorkAreaFactory { - -WorkArea * create(LyXView & owner, int w, int h) -{ - return new QWorkArea(owner, w, h); -} - -} // namespace WorkAreaFactory diff --git a/src/frontends/qt4/lyx_gui.C b/src/frontends/qt4/lyx_gui.C index ef49d88317..84d674575b 100644 --- a/src/frontends/qt4/lyx_gui.C +++ b/src/frontends/qt4/lyx_gui.C @@ -5,6 +5,7 @@ * * \author unknown * \author John Levon + * \author Abdelrazak Younes * * Full author contact details are available in file CREDITS. */ @@ -35,10 +36,6 @@ #include "support/package.h" #include "debug.h" -// Dear Lord, deliver us from Evil, aka the Qt headers -// Qt defines a macro 'signals' that clashes with a boost namespace. -// All is well if the namespace is visible first. -#include // FIXME: Is this needed? (Lgb) #include #include @@ -48,10 +45,7 @@ #include "QLImage.h" #include "qt_helpers.h" #include "socket_callback.h" - -#ifdef Q_WS_MACX -#include -#endif +#include "Application.h" #include #include @@ -60,10 +54,13 @@ #include #include + + using lyx::support::ltrim; using lyx::support::package; using lyx::frontend::QtView; +using lyx::frontend::Application; namespace os = lyx::support::os; @@ -77,9 +74,6 @@ using std::map; using std::vector; using std::string; - -extern BufferList bufferlist; - // FIXME: wrong place ! LyXServer * lyxserver; LyXServerSocket * lyxsocket; @@ -107,78 +101,45 @@ void cleanup() // in QLyXKeySym.C extern void initEncodings(); -#ifdef Q_WS_X11 -extern bool lyxX11EventFilter(XEvent * xev); -#endif - -#ifdef Q_WS_MACX -extern bool macEventFilter(EventRef event); -extern pascal OSErr -handleOpenDocuments(const AppleEvent* inEvent, AppleEvent* /*reply*/, - long /*refCon*/); -#endif - -class LQApplication : public QApplication -{ -public: - LQApplication(int & argc, char ** argv); -#ifdef Q_WS_X11 - bool x11EventFilter (XEvent * ev) { return lyxX11EventFilter(ev); } -#endif -#ifdef Q_WS_MACX - bool macEventFilter(EventRef event); -#endif -}; - - -LQApplication::LQApplication(int & argc, char ** argv) - : QApplication(argc, argv) -{ -#ifdef Q_WS_MACX - AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, - NewAEEventHandlerUPP(handleOpenDocuments), - 0, false); -#endif -} - - -#ifdef Q_WS_MACX -bool LQApplication::macEventFilter(EventRef event) -{ - if (GetEventClass(event) == kEventClassAppleEvent) { - EventRecord eventrec; - ConvertEventRefToEventRecord(event, &eventrec); - AEProcessAppleEvent(&eventrec); - - return false; - } - return false; -} -#endif - - namespace lyx_gui { bool use_gui = true; - void exec(int & argc, char * argv[]) { + /* + FIXME : Abdel 29/05/2006 (younes.a@free.fr) + reorganize this code. In particular make sure that this + advice from Qt documentation is respected: + + Since the QApplication object does so much initialization, it + must be created before any other objects related to the user + interface are created. + + Right now this is not the case, I suspect that a number of global variables + contains Qt object that are initialized before the passage through + parse_init(). This might also explain the message displayed by Qt + that caused the hanging: + + QObject::killTimer: timers cannot be stopped from another thread + */ + // Force adding of font path _before_ QApplication is initialized FontLoader::initFontPath(); #ifdef Q_WS_WIN - static LQApplication app(argc, argv); + static Application app(argc, argv); #else - LQApplication app(argc, argv); + Application app(argc, argv); #endif + // install translation file for Qt built-in dialogs // These are only installed since Qt 3.2.x QTranslator qt_trans; QString language_name = QString("qt_") + QLocale::system().name(); language_name.truncate(5); - if (qt_trans.load(language_name, + if (qt_trans.load(language_name, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { qApp->installTranslator(&qt_trans); diff --git a/src/frontends/screen.C b/src/frontends/screen.C deleted file mode 100644 index dcd022172c..0000000000 --- a/src/frontends/screen.C +++ /dev/null @@ -1,260 +0,0 @@ -/** - * \file screen.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - * - * Splash screen code added by Angus Leeming - */ - -#include - -#include "screen.h" -#include "font_metrics.h" -#include "lyx_gui.h" -#include "Painter.h" -#include "WorkArea.h" - -#include "BufferView.h" -#include "buffer.h" -#include "bufferparams.h" -#include "coordcache.h" -#include "cursor.h" -#include "debug.h" -#include "language.h" -#include "LColor.h" -#include "lyxfont.h" -#include "lyxrc.h" -#include "lyxrow.h" -#include "lyxtext.h" -#include "metricsinfo.h" -#include "paragraph.h" -#include "rowpainter.h" -#include "version.h" - -#include "graphics/GraphicsImage.h" -#include "graphics/GraphicsLoader.h" - -#include "support/filetools.h" // LibFileSearch - -#include -#include -#include - -using lyx::support::libFileSearch; - -using std::endl; -using std::min; -using std::max; -using std::string; - - -namespace { - -class SplashScreen : boost::noncopyable, boost::signals::trackable { -public: - /// This is a singleton class. Get the instance. - static SplashScreen const & get(); - /// - lyx::graphics::Image const * image() const { return loader_.image(); } - /// - string const & text() const { return text_; } - /// - LyXFont const & font() const { return font_; } - /// - void connect(lyx::graphics::Loader::slot_type const & slot) const { - loader_.connect(slot); - } - /// - void startLoading() const { - if (loader_.status() == lyx::graphics::WaitingToLoad) - loader_.startLoading(); - } - -private: - /** Make the c-tor private so we can control how many objects - * are instantiated. - */ - SplashScreen(); - - /// - lyx::graphics::Loader loader_; - /// The text to be written on top of the pixmap - string const text_; - /// in this font... - LyXFont font_; -}; - - -SplashScreen const & SplashScreen::get() -{ - static SplashScreen singleton; - return singleton; -} - - -SplashScreen::SplashScreen() - : text_(lyx_version ? lyx_version : "unknown") -{ - if (!lyxrc.show_banner) - return; - - string const file = libFileSearch("images", "banner", "ppm"); - if (file.empty()) - return; - - // The font used to display the version info - font_.setFamily(LyXFont::SANS_FAMILY); - font_.setSeries(LyXFont::BOLD_SERIES); - font_.setSize(LyXFont::SIZE_NORMAL); - font_.setColor(LColor::yellow); - - // Load up the graphics file - loader_.reset(file); -} - -} // namespace anon - - -LyXScreen::LyXScreen() - : greyed_out_(true), cursor_visible_(false) -{ - // Start loading the pixmap as soon as possible - if (lyxrc.show_banner) { - SplashScreen const & splash = SplashScreen::get(); - splash.connect(boost::bind(&LyXScreen::checkAndGreyOut, this)); - splash.startLoading(); - } -} - - -LyXScreen::~LyXScreen() -{ -} - - -void LyXScreen::checkAndGreyOut() -{ - if (greyed_out_) - greyOut(); -} - - -void LyXScreen::showCursor(BufferView & bv) -{ - if (cursor_visible_) - return; - - if (!bv.available()) - return; - - Cursor_Shape shape = BAR_SHAPE; - - LyXText const & text = *bv.getLyXText(); - LyXFont const & realfont = text.real_current_font; - BufferParams const & bp = bv.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; - - LyXFont const font = bv.cursor().getFont(); - int const asc = font_metrics::maxAscent(font); - int const des = font_metrics::maxDescent(font); - int h = asc + des; - int x = 0; - int y = 0; - bv.cursor().getPos(x, y); - y -= asc; - //lyxerr << "LyXScreen::showCursor x: " << x << " y: " << y << endl; - - // if it doesn't touch the screen, don't try to show it - if (y + h < 0 || y >= workarea().workHeight()) - return; - - cursor_visible_ = true; - showCursor(x, y, h, shape); -} - - -void LyXScreen::hideCursor() -{ - if (!cursor_visible_) - return; - - cursor_visible_ = false; - removeCursor(); -} - - -void LyXScreen::toggleCursor(BufferView & bv) -{ - if (cursor_visible_) - hideCursor(); - else - showCursor(bv); -} - - -void LyXScreen::prepareCursor() -{ - cursor_visible_ = false; -} - - -void LyXScreen::redraw(BufferView & bv, ViewMetricsInfo const & vi) -{ - greyed_out_ = false; - workarea().getPainter().start(); - paintText(bv, vi); - lyxerr[Debug::DEBUG] << "Redraw screen" << endl; - int const ymin = std::max(vi.y1, 0); - int const ymax = - ( vi.p2 < vi.size - 1 ? vi.y2 : workarea().workHeight() ); - expose(0, ymin, workarea().workWidth(), ymax - ymin); - workarea().getPainter().end(); - theCoords.doneUpdating(); -} - - -void LyXScreen::greyOut() -{ - greyed_out_ = true; - workarea().getPainter().start(); - - workarea().getPainter().fillRectangle(0, 0, - workarea().workWidth(), - workarea().workHeight(), - LColor::bottomarea); - - // Add a splash screen to the centre of the work area - SplashScreen const & splash = SplashScreen::get(); - lyx::graphics::Image const * const splash_image = splash.image(); - if (splash_image) { - int const w = splash_image->getWidth(); - int const h = splash_image->getHeight(); - - int x = (workarea().workWidth() - w) / 2; - int y = (workarea().workHeight() - h) / 2; - - workarea().getPainter().image(x, y, w, h, *splash_image); - - x += 260; - y += 265; - - workarea().getPainter().text(x, y, splash.text(), splash.font()); - } - expose(0, 0, workarea().workWidth(), workarea().workHeight()); - workarea().getPainter().end(); -} diff --git a/src/frontends/screen.h b/src/frontends/screen.h deleted file mode 100644 index 1c2825fc1b..0000000000 --- a/src/frontends/screen.h +++ /dev/null @@ -1,96 +0,0 @@ -// -*- C++ -*- -/** - * \file screen.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author unknown - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef SCREEN_H -#define SCREEN_H - - -class LyXText; -class CursorSlice; -class WorkArea; -class BufferView; -class ViewMetricsInfo; - - -/** - * LyXScreen - document rendering management - * - * This class is used to manage the on-screen rendering inside the - * work area; it is responsible for deciding which LyXText rows - * need re-drawing. - * - * This class will arrange for LyXText to paint onto a pixmap - * provided by the WorkArea widget. - * - * The blinking cursor is also handled here. - */ -class LyXScreen { -public: - LyXScreen(); - - virtual ~LyXScreen(); - - /// redraw the screen, without using existing pixmap - virtual void redraw(BufferView & bv, ViewMetricsInfo const & vi); - - /// grey out (no buffer) - void greyOut(); - - /// hide the visible cursor, if it is visible - void hideCursor(); - - /// show the cursor if it is not visible - void showCursor(BufferView & bv); - - /// toggle the cursor's visibility - void toggleCursor(BufferView & bv); - - /// set cursor_visible_ to false in prep for re-display - void prepareCursor(); - - -protected: - /// cause the display of the given area of the work area - virtual void expose(int x, int y, int w, int h) = 0; - - /// get the work area - virtual WorkArea & workarea() = 0; - - /// types of cursor in work area - enum Cursor_Shape { - /// 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 - }; - - /// paint the cursor and store the background - virtual void showCursor(int x, int y, int h, Cursor_Shape shape) = 0; - - /// hide the cursor - virtual void removeCursor() = 0; - -private: - /// - void checkAndGreyOut(); - - /// - bool greyed_out_; - - /// is the cursor currently displayed - bool cursor_visible_; - -}; - -#endif // SCREEN_H diff --git a/src/frontends/xforms/GuiClipboard.h b/src/frontends/xforms/GuiClipboard.h new file mode 100644 index 0000000000..04ab2f2a34 --- /dev/null +++ b/src/frontends/xforms/GuiClipboard.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +/** + * \file xforms/GuiClipboard.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef CLIPBOARD_H +#define CLIPBOARD_H + +#include "frontends/Clipboard.h" + +#include "XWorkArea.h" + +namespace lyx { +namespace frontend { + +typedef XWorkArea FWorkArea; + +/** + * The XForms version of the Clipboard. + */ +class GuiClipboard: public lyx::frontend::Clipboard +{ +public: + GuiClipboard(FWorkArea * work_area) + : old_work_area_(work_area) + { + } + + virtual ~GuiClipboard() {} + + /** ClipBoard overloaded methods + */ + //@{ + void haveSelection(bool own) + { + old_work_area_->haveSelection(own); + } + + std::string const get() const + { + return old_work_area_->getClipboard(); + } + + void put(std::string const & str) + { + old_work_area_->putClipboard(str); + } + //@} + +private: + FWorkArea * old_work_area_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // CLIPBOARD_H diff --git a/src/frontends/xforms/GuiImplementation.h b/src/frontends/xforms/GuiImplementation.h new file mode 100644 index 0000000000..124b7081af --- /dev/null +++ b/src/frontends/xforms/GuiImplementation.h @@ -0,0 +1,91 @@ +// -*- C++ -*- +/** + * \file xforms/GuiImplementation.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef GUI_IMPLEMENTATION_H +#define GUI_IMPLEMENTATION_H + +#include "frontends/Gui.h" +#include "frontends/LyXView.h" + +#include "xscreen.h" +#include "XWorkArea.h" + +#include "GuiClipboard.h" +#include "GuiWorkArea.h" + +#include + +#include + +namespace lyx { +namespace frontend { + +typedef XScreen FScreen; +typedef XWorkArea FWorkArea; + +/** + * The Gui class is the interface to all XForms components. + */ +class GuiImplementation: public lyx::frontend::Gui +{ +public: + GuiImplementation(LyXView & owner): owner_(owner) + { + } + + virtual ~GuiImplementation() + { + } + + lyx::frontend::Clipboard& clipboard() + { + return *clipboard_; + } + + int newWorkArea(int w, int h) + { + old_work_area_.reset(new FWorkArea(owner_, w, h)); + old_screen_.reset(new FScreen(*old_work_area_.get())); + work_area_.reset(new GuiWorkArea(owner_, w, h, old_screen_.get(), old_work_area_.get())); + clipboard_.reset(new GuiClipboard(old_work_area_.get())); + guiCursor().connect(work_area_.get()); + } + + lyx::frontend::WorkArea& workArea(int id) + { + return *work_area_; + } + + void destroyWorkArea(int id) + { + clipboard_.reset(); + work_area_.reset(); + old_work_area_.reset(); + old_screen_.reset(); + } + +private: + /// + boost::shared_ptr clipboard_; + /// + boost::shared_ptr work_area_; + /// + boost::shared_ptr old_work_area_; + /// + boost::shared_ptr old_screen_; + /// + LyXView & owner_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // GUI_IMPLEMENTATION_H diff --git a/src/frontends/xforms/GuiWorkArea.h b/src/frontends/xforms/GuiWorkArea.h new file mode 100644 index 0000000000..a595e6fc7b --- /dev/null +++ b/src/frontends/xforms/GuiWorkArea.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +/** + * \file xforms/WorkArea.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Abdelrazak Younes + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef WORKAREA_H +#define WORKAREA_H + +#include "frontends/WorkArea.h" + +#include "xscreen.h" +#include "XWorkArea.h" + +namespace lyx { +namespace frontend { + +typedef XScreen FScreen; +typedef XWorkArea FWorkArea; + +/** + * Temporary wrapper around XWorkArea and XScreen. + * Please refer to the Qt4 implementation for a proper cleanup of the API. + */ +class GuiWorkArea: public lyx::frontend::WorkArea { +public: + GuiWorkArea(LyXView & owner, int w, int h, + FScreen * screen, FWorkArea * work_area) + : lyx::frontend::WorkArea(owner, w, h), + old_screen_(screen), old_work_area_(work_area) + { + } + + ~GuiWorkArea() {} + + /// return the painter object for this work area + virtual lyx::frontend::Painter & getPainter() + { + return old_work_area_->getPainter(); + } + + /// return the width of the work area in pixels + virtual int width() const + { + return old_work_area_->workWidth(); + } + + /// return the height of the work area in pixels + virtual int height() const + { + return old_work_area_->workHeight(); + } + + /** + * Update the scrollbar. + * @param height the total document height in pixels + * @param pos the current position in the document, in pixels + * @param line_height the line-scroll amount, in pixels + */ + virtual void setScrollbarParams(int height, int pos, int line_height) + { + old_work_area_->setScrollbarParams(height, pos, line_height); + } + + + /// paint the cursor and store the background + virtual void showCursor(int x, int y, int h, Cursor_Shape shape) + { + old_screen_->showCursor(x, y, h, shape); + } + + /// hide the cursor + virtual void removeCursor() + { + old_screen_->removeCursor(); + } + +protected: + /// cause the display of the given area of the work area + virtual void expose(int x, int y, int w, int h) + { + old_screen_->expose(x, y, w, h); + } + +private: + FScreen * old_screen_; + FWorkArea * old_work_area_; +}; + +} // namespace frontend +} // namespace lyx + +#endif // WORKAREA_H diff --git a/src/frontends/xforms/LyXScreenFactory.C b/src/frontends/xforms/LyXScreenFactory.C deleted file mode 100644 index 6e007f0de8..0000000000 --- a/src/frontends/xforms/LyXScreenFactory.C +++ /dev/null @@ -1,29 +0,0 @@ -/** - * \file xforms/LyXScreenFactory.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "frontends/LyXScreenFactory.h" - -#include "xscreen.h" -#include "XWorkArea.h" - - -namespace LyXScreenFactory { - -LyXScreen * create(WorkArea & owner) -{ - using lyx::frontend::XScreen; - using lyx::frontend::XWorkArea; - - return new XScreen(static_cast(owner)); -} - -} diff --git a/src/frontends/xforms/Makefile.am b/src/frontends/xforms/Makefile.am index ed4d9a1635..a7afd7cd64 100644 --- a/src/frontends/xforms/Makefile.am +++ b/src/frontends/xforms/Makefile.am @@ -156,10 +156,12 @@ libxforms_la_SOURCES = \ FormVSpace.h \ FormWrap.C \ FormWrap.h \ + GuiClipboard.h \ + GuiImplementation.h \ + GuiWorkArea.h \ LayoutEngine.C \ LayoutEngine.h \ LyXKeySymFactory.C \ - LyXScreenFactory.C \ XFormsMenubar.C \ XFormsMenubar.h \ RadioButtonGroup.C \ @@ -168,7 +170,6 @@ libxforms_la_SOURCES = \ XFormsToolbar.h \ Tooltips.C \ Tooltips.h \ - WorkAreaFactory.C \ XFormsView.C \ XFormsView.h \ XLyXKeySym.C \ diff --git a/src/frontends/xforms/WorkAreaFactory.C b/src/frontends/xforms/WorkAreaFactory.C deleted file mode 100644 index 3b186a1f3e..0000000000 --- a/src/frontends/xforms/WorkAreaFactory.C +++ /dev/null @@ -1,24 +0,0 @@ -/** - * \file xforms/WorkAreaFactory.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author John Levon - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "frontends/WorkAreaFactory.h" -#include "XWorkArea.h" - - -namespace WorkAreaFactory { - -WorkArea * create(LyXView & owner, int w, int h) -{ - return new lyx::frontend::XWorkArea(owner, w, h); -} - -} diff --git a/src/frontends/xforms/XFormsView.C b/src/frontends/xforms/XFormsView.C index 86dfcbc544..62410a03e4 100644 --- a/src/frontends/xforms/XFormsView.C +++ b/src/frontends/xforms/XFormsView.C @@ -74,7 +74,7 @@ void print_metrics(std::ostream & os, std::string const & name, Box const & box) XFormsView::XFormsView(int width, int height) : LyXView(), window_(Box(width, height)), - icon_pixmap_(0), icon_mask_(0) + icon_pixmap_(0), icon_mask_(0), frontend_(*this) { int const air = 2; diff --git a/src/frontends/xforms/XFormsView.h b/src/frontends/xforms/XFormsView.h index 45e58ff870..91099b00db 100644 --- a/src/frontends/xforms/XFormsView.h +++ b/src/frontends/xforms/XFormsView.h @@ -12,6 +12,7 @@ #ifndef LyXView_H #define LyXView_H +#include "GuiImplementation.h" #include "LayoutEngine.h" #include "forms_fwd.h" @@ -82,6 +83,9 @@ public: // returns true if this view has the focus. virtual bool hasFocus() const; + /// + Gui & gui() { return frontend_; } + private: /** * setWindowTitle - set title of window @@ -116,6 +120,8 @@ private: Pixmap icon_pixmap_; /// Pixmap icon_mask_; + /// + GuiImplementation frontend_; }; } // namespace frontend diff --git a/src/frontends/xforms/XWorkArea.C b/src/frontends/xforms/XWorkArea.C index df5d263264..b4e131ef75 100644 --- a/src/frontends/xforms/XWorkArea.C +++ b/src/frontends/xforms/XWorkArea.C @@ -613,7 +613,7 @@ int XWorkArea::event_cb(XEvent * xev) } -void XWorkArea::haveSelection(bool yes) const +void XWorkArea::haveSelection(bool yes) { Window const owner = yes ? FL_ObjWin(work_area) : None; XSetSelectionOwner(fl_get_display(), XA_PRIMARY, owner, CurrentTime); @@ -642,7 +642,7 @@ string const XWorkArea::getClipboard() const } -void XWorkArea::putClipboard(string const & s) const +void XWorkArea::putClipboard(string const & s) { static string hold; hold = s; diff --git a/src/frontends/xforms/XWorkArea.h b/src/frontends/xforms/XWorkArea.h index 9138fdd50a..2f83c933a6 100644 --- a/src/frontends/xforms/XWorkArea.h +++ b/src/frontends/xforms/XWorkArea.h @@ -14,6 +14,7 @@ #define XWORKAREA_H #include "frontends/WorkArea.h" +#include "frontends/Clipboard.h" #include "XPainter.h" #include "LayoutEngine.h" @@ -25,7 +26,7 @@ class LyXView; namespace lyx { namespace frontend { -class XWorkArea : public WorkArea { +class XWorkArea { public: /// XWorkArea(LyXView & owner, int width, int height); @@ -56,11 +57,11 @@ public: /// xforms callback from scrollbar void scroll_cb(); /// a selection exists - virtual void haveSelection(bool) const; + virtual void haveSelection(bool); /// virtual std::string const getClipboard() const; /// - virtual void putClipboard(std::string const &) const; + virtual void putClipboard(std::string const &); /// handles SelectionRequest X Event, to fill the clipboard int event_cb(XEvent * xev); diff --git a/src/frontends/xforms/xscreen.C b/src/frontends/xforms/xscreen.C index 1c903ba878..640b881f63 100644 --- a/src/frontends/xforms/xscreen.C +++ b/src/frontends/xforms/xscreen.C @@ -45,7 +45,7 @@ GC createGC() XScreen::XScreen(XWorkArea & o) - : LyXScreen(), owner_(o), nocursor_pixmap_(0), + : owner_(o), nocursor_pixmap_(0), cursor_x_(0), cursor_y_(0), cursor_w_(0), cursor_h_(0) { // We need this GC @@ -59,12 +59,6 @@ XScreen::~XScreen() } -WorkArea & XScreen::workarea() -{ - return owner_; -} - - void XScreen::setCursorColor() { if (!lyxColorHandler.get()) diff --git a/src/frontends/xforms/xscreen.h b/src/frontends/xforms/xscreen.h index 829ac96230..27f1d2c3f4 100644 --- a/src/frontends/xforms/xscreen.h +++ b/src/frontends/xforms/xscreen.h @@ -13,7 +13,8 @@ #ifndef XSCREEN_H #define XSCREEN_H -#include "screen.h" +#include "frontends/GuiCursor.h" + #include // for Pixmap, GC class WorkArea; @@ -28,7 +29,7 @@ class XWorkArea; date and used to optimize drawing on the screen. This class also handles the drawing of the cursor and partly the selection. */ -class XScreen : public LyXScreen { +class XScreen { public: /// XScreen(XWorkArea &); @@ -39,10 +40,6 @@ public: /// Sets the cursor color to LColor::cursor. virtual void setCursorColor(); -protected: - /// get the work area - virtual WorkArea & workarea(); - /// Copies specified area of pixmap to screen virtual void expose(int x, int y, int w, int h); diff --git a/src/insets/insetcollapsable.h b/src/insets/insetcollapsable.h index 9455eabbb2..61493dac23 100644 --- a/src/insets/insetcollapsable.h +++ b/src/insets/insetcollapsable.h @@ -20,11 +20,17 @@ #include "box.h" #include "lyxfont.h" -class Painter; class LyXText; class Paragraph; class CursorSlice; +namespace lyx { +namespace frontend { +class Painter; +} +} + + /** A collapsable text inset */ diff --git a/src/insets/insetline.C b/src/insets/insetline.C index 3a256920ea..62d7242142 100644 --- a/src/insets/insetline.C +++ b/src/insets/insetline.C @@ -21,6 +21,8 @@ #include "frontends/Painter.h" +using lyx::frontend::Painter; + using std::endl; using std::ostream; diff --git a/src/insets/insetpagebreak.C b/src/insets/insetpagebreak.C index d86a826be5..cb417630c7 100644 --- a/src/insets/insetpagebreak.C +++ b/src/insets/insetpagebreak.C @@ -21,6 +21,8 @@ #include "frontends/Painter.h" #include "frontends/font_metrics.h" +using lyx::frontend::Painter; + using std::endl; using std::ostream; diff --git a/src/insets/insettabular.C b/src/insets/insettabular.C index 5b1bc8b814..95e27e5f0c 100644 --- a/src/insets/insettabular.C +++ b/src/insets/insettabular.C @@ -53,6 +53,8 @@ using lyx::graphics::PreviewLoader; using lyx::support::ltrim; +using lyx::frontend::Painter; + using boost::shared_ptr; using std::auto_ptr; @@ -284,7 +286,7 @@ void InsetTabular::draw(PainterInfo & pi, int x, int y) const //lyxerr << "InsetTabular::draw: " << x << " " << y << endl; BufferView * bv = pi.base.bv; - static NullPainter nop; + static lyx::frontend::NullPainter nop; static PainterInfo nullpi(bv, nop); //resetPos(bv->cursor()); diff --git a/src/insets/insettabular.h b/src/insets/insettabular.h index 5f14aeef73..145f854812 100644 --- a/src/insets/insettabular.h +++ b/src/insets/insettabular.h @@ -37,13 +37,18 @@ class FuncStatus; class LyXLex; -class Painter; class BufferView; class Buffer; class BufferParams; class Paragraph; class CursorSlice; +namespace lyx { +namespace frontend { +class Painter; +} +} + class InsetTabular : public InsetOld { public: @@ -154,7 +159,7 @@ private: virtual std::auto_ptr doClone() const; /// - void drawCellLines(Painter &, int x, int y, row_type row, + void drawCellLines(lyx::frontend::Painter &, int x, int y, row_type row, idx_type cell, bool erased) const; /// void setCursorFromCoordinates(LCursor & cur, int x, int y) const; diff --git a/src/lyxtext.h b/src/lyxtext.h index dbb957d774..8eb3931562 100644 --- a/src/lyxtext.h +++ b/src/lyxtext.h @@ -334,9 +334,6 @@ public: /// delete double space or empty paragraphs around old cursor bool deleteEmptyParagraphMechanism(LCursor & cur, LCursor & old); - /// - friend class LyXScreen; - public: /// Dimension dim_; diff --git a/src/mathed/math_nestinset.C b/src/mathed/math_nestinset.C index 05af753038..d4967a7048 100644 --- a/src/mathed/math_nestinset.C +++ b/src/mathed/math_nestinset.C @@ -229,7 +229,7 @@ void MathNestInset::drawSelection(PainterInfo & pi, int x, int y) const return; // FIXME: hack to get position cache warm - static NullPainter nop; + static lyx::frontend::NullPainter nop; PainterInfo pinop(pi); pinop.pain = nop; draw(pinop, x, y); diff --git a/src/mathed/math_support.C b/src/mathed/math_support.C index 0b8c139ddb..7832135bc7 100644 --- a/src/mathed/math_support.C +++ b/src/mathed/math_support.C @@ -27,6 +27,7 @@ #include #include +using lyx::frontend::Painter; using std::string; using std::max; diff --git a/src/metricsinfo.C b/src/metricsinfo.C index 9d6568640c..63d6f2eae3 100644 --- a/src/metricsinfo.C +++ b/src/metricsinfo.C @@ -46,7 +46,7 @@ MetricsInfo::MetricsInfo(BufferView * bv, LyXFont const & font, int textwidth) -PainterInfo::PainterInfo(BufferView * bv, Painter & painter) +PainterInfo::PainterInfo(BufferView * bv, lyx::frontend::Painter & painter) : pain(painter), ltr_pos(false), erased_(false) { base.bv = bv; diff --git a/src/metricsinfo.h b/src/metricsinfo.h index e7d3eeb360..8416311695 100644 --- a/src/metricsinfo.h +++ b/src/metricsinfo.h @@ -17,9 +17,14 @@ #include -class Painter; class BufferView; +namespace lyx { +namespace frontend { +class Painter; +} +} + /// Standard Sizes (mode styles) enum Styles { @@ -80,7 +85,7 @@ public: class PainterInfo { public: /// - PainterInfo(BufferView * bv, Painter & pain); + PainterInfo(BufferView * bv, lyx::frontend::Painter & pain); /// void draw(int x, int y, char c); /// @@ -89,7 +94,7 @@ public: /// MetricsBase base; /// - Painter & pain; + lyx::frontend::Painter & pain; /// Whether the text at this point is right-to-left (for InsetNewline) bool ltr_pos; /// Whether the parent is deleted (change tracking) diff --git a/src/rowpainter.C b/src/rowpainter.C index 3945d80ae7..a82f7fa3bc 100644 --- a/src/rowpainter.C +++ b/src/rowpainter.C @@ -42,6 +42,8 @@ #include +using lyx::frontend::Painter; +using lyx::frontend::NullPainter; using lyx::char_type; using lyx::pos_type; using lyx::pit_type; diff --git a/src/support/lstrings.C b/src/support/lstrings.C index b4b70f0f0c..fe8a86c5a1 100644 --- a/src/support/lstrings.C +++ b/src/support/lstrings.C @@ -546,6 +546,27 @@ int findToken(char const * const str[], string const & search_token) } +string const externalLineEnding(string const & str) +{ +#if defined(__APPLE__) + // The MAC clipboard uses \r for lineendings, and we use \n + return subst(str, '\n', '\r'); +#elif defined (_WIN32) || (defined (__CYGWIN__) && defined (X_DISPLAY_MISSING)) + // Windows clipboard uses \r\n for lineendings, and we use \n + return subst(str, "\n", "\r\n"); +#else + return str; +#endif +} + + +string const internalLineEnding(string const & str) +{ + string s = subst(str, "\r\n", "\n"); + return subst(s, '\r', '\n'); +} + + #ifndef I_AM_NOT_AFRAID_OF_HEADER_LIBRARIES #if USE_BOOST_FORMAT diff --git a/src/support/lstrings.h b/src/support/lstrings.h index 0ef0806edd..2b03e42b78 100644 --- a/src/support/lstrings.h +++ b/src/support/lstrings.h @@ -180,6 +180,12 @@ std::string const getStringFromVector(std::vector const & vec, /// found, else -1. The last item in \p str must be "". int findToken(char const * const str[], std::string const & search_token); +/// Convert internal line endings to line endings as expected by the OS +std::string const externalLineEnding(std::string const & str); + +/// Convert line endings in any formnat to internal line endings +std::string const internalLineEnding(std::string const & str); + #ifdef I_AM_NOT_AFRAID_OF_HEADER_LIBRARIES