A layout engine for XForms.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8704 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Angus Leeming 2004-04-28 17:22:05 +00:00
parent dd01380a27
commit b03580df17
31 changed files with 994 additions and 151 deletions

View File

@ -187,8 +187,6 @@ src/output_plaintext.C
src/paragraph.C
src/rowpainter.C
src/support/globbing.C
src/support/path_defines.C
src/tex2lyx/lengthcommon.C
src/text.C
src/text2.C
src/text3.C

View File

@ -65,9 +65,8 @@ using std::vector;
extern BufferList bufferlist;
BufferView::BufferView(LyXView * owner, int xpos, int ypos,
int width, int height)
: pimpl_(new Pimpl(*this, owner, xpos, ypos, width, height))
BufferView::BufferView(LyXView * owner, int width, int height)
: pimpl_(new Pimpl(*this, owner, width, height))
{}

View File

@ -54,7 +54,7 @@ public:
* Create a view with the given owner main window,
* of the given dimensions.
*/
BufferView(LyXView * owner, int x, int y, int w, int h);
BufferView(LyXView * owner, int w, int h);
~BufferView();

View File

@ -115,13 +115,13 @@ boost::signals::connection lostcon;
BufferView::Pimpl::Pimpl(BufferView & bv, LyXView * owner,
int xpos, int ypos, int width, int height)
int width, int height)
: bv_(&bv), owner_(owner), buffer_(0), cursor_timeout(400),
using_xterm_cursor(false), cursor_(bv)
{
xsel_cache_.set = false;
workarea_.reset(WorkAreaFactory::create(*owner_, xpos, ypos, width, height));
workarea_.reset(WorkAreaFactory::create(*owner_, width, height));
screen_.reset(LyXScreenFactory::create(workarea()));
// Setup the signals

View File

@ -46,8 +46,7 @@ class FuncStatus;
///
struct BufferView::Pimpl : public boost::signals::trackable {
///
Pimpl(BufferView & bv, LyXView * owner,
int xpos, int ypos, int width, int height);
Pimpl(BufferView & bv, LyXView * owner, int width, int height);
///
Painter & painter() const;
/// return the screen for this bview

View File

@ -1,3 +1,9 @@
2004-04-28 Angus Leeming <leeming@lyx.org>
* BufferView.[Ch] (c-tor):
* BufferView_pimpl.[Ch] (c-tor): no longer receives x,y position.
No longer passes these data to the WorkArea generator.
2004-04-28 Angus Leeming <leeming@lyx.org>
* BufferView_pimpl.C (c-tor): pass LyXView & to WorkArea generator.

View File

@ -1,3 +1,8 @@
2004-04-28 Angus Leeming <leeming@lyx.org>
* WorkAreaFactory.h (create): passed a LyXView &.
No longer passed x, y data.
2004-04-27 Angus Leeming <leeming@lyx.org>
* Dialogs.h: add myself as author.

View File

@ -20,7 +20,7 @@ namespace WorkAreaFactory {
* Make a work area. Used because we want to generate
* a toolkit-specific instance.
*/
WorkArea * create(LyXView & owner, int x, int y, int w, int h);
WorkArea * create(LyXView & owner, int w, int h);
}
#endif // WORKAREA_FACTORY_H

View File

@ -1,3 +1,9 @@
2004-04-28 Angus Leeming <leeming@lyx.org>
* WorkAreaFactory.C (create): No longer passed x, y data.
* GView.[Ch] (c-tor): no longer passes x, y data to BufferView c-tor.
2004-04-28 Angus Leeming <leeming@lyx.org>
* WorkAreaFactory.C (create): pass a LyXView & to GWorkArea c-tor.

View File

@ -83,7 +83,7 @@ GView::GView()
menubar_.reset(new GMenubar(this, menubackend));
toolbar_.reset(new GToolbar(this, 0, 0));
toolbar_->init();
bufferview_.reset(new BufferView(this, 0, 0, 300, 300));
bufferview_.reset(new BufferView(this, 300, 300));
minibuffer_.reset(new GMiniBuffer(this, *controlcommand_));
focus_command_buffer.connect(

View File

@ -19,7 +19,7 @@
namespace WorkAreaFactory {
WorkArea * create(LyXView & owner, int /*x*/, int /*y*/, int w, int h)
WorkArea * create(LyXView & owner, int w, int h)
{
return new GWorkArea(owner, w, h);
}

View File

@ -1,3 +1,11 @@
2004-04-28 Angus Leeming <leeming@lyx.org>
* WorkAreaFactory.C (create): No longer passed x, y data.
* QWorkArea.[Ch] (c-tor): No longer receives x, y data.
* QtView.[Ch] (c-tor): no longer passes x, y data to BufferView c-tor.
2004-04-28 Angus Leeming <leeming@lyx.org>
* WorkAreaFactory.C (create): pass a LyXView & to QWorkArea c-tor.

View File

@ -39,7 +39,7 @@ namespace {
QWorkArea const * wa_ptr = 0;
}
QWorkArea::QWorkArea(LyXView &, int, int, int, int)
QWorkArea::QWorkArea(LyXView &, int, int)
: WorkArea(), QWidget(qApp->mainWidget()), painter_(*this)
{
scrollbar_ = new QScrollBar(QScrollBar::Vertical, this);

View File

@ -35,7 +35,7 @@ class QWorkArea : public WorkArea, public QWidget {
public:
friend class QContentPane;
QWorkArea(LyXView & owner, int x, int y, int w, int h);
QWorkArea(LyXView & owner, int w, int h);
virtual ~QWorkArea();
/// return this widget's painter

View File

@ -49,7 +49,7 @@ QtView::QtView(unsigned int width, unsigned int height)
qApp->setMainWidget(this);
bufferview_.reset(new BufferView(this, 0, 0, width, height));
bufferview_.reset(new BufferView(this, width, height));
menubar_.reset(new QLMenubar(this, menubackend));
toolbar_.reset(new QLToolbar(this));

View File

@ -15,9 +15,9 @@
namespace WorkAreaFactory {
WorkArea * create(LyXView & owner, int x, int y, int w, int h)
WorkArea * create(LyXView & owner, int w, int h)
{
return new QWorkArea(owner, x, y, w, h);
return new QWorkArea(owner, w, h);
}
} // namespace WorkAreaFactory

View File

@ -1,3 +1,18 @@
2004-04-28 Angus Leeming <leeming@lyx.org>
* LayoutEngine.[Ch]: a layout engine for xforms, drawing heavily
on GTK+ code for inspiration.
* Makefile.am: add new files.
* WorkAreaFactory.C (create): no longer pass x,y data to XWorkArea.
* XFormsMenubar.[Ch]:
* XFormsToolbar.[Ch]:
* XFormsView.[Ch]:
* XMiniBuffer.[Ch]:
* XWorkArea.[Ch]: adjustments to use the new layout engine.
2004-04-28 Angus Leeming <leeming@lyx.org>
* WorkAreaFactory.C (create): pass a LyXView & to QWorkArea c-tor.

View File

@ -0,0 +1,468 @@
// -*- C++ -*-
/**
* \file LayoutEngine.C
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Angus Leeming
*
* Full author contact details are available in file CREDITS.
*
* A generic layout engine.
*
* Draws heavily on the GTK+ files gtkbox.[ch], gtkhbox.[ch],
* for both inspiration and implementation,
* and from which this notice is taken:
*
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include "LayoutEngine.h"
#include "lyx_forms.h"
#include <boost/assert.hpp>
namespace lyx {
namespace frontend {
bool BoxList::empty() const
{
return data_.empty();
}
BoxList::size_type BoxList::size() const
{
return data_.size();
}
void BoxList::clear()
{
data_.clear();
}
Box & BoxList::push_back(Box const & box)
{
data_.push_back(box);
return data_.back();
}
BoxList::iterator BoxList::begin()
{
return data_.begin();
}
BoxList::iterator BoxList::end()
{
return data_.end();
}
BoxList::const_iterator BoxList::begin() const
{
return data_.begin();
}
BoxList::const_iterator BoxList::end() const
{
return data_.end();
}
BoxList::iterator BoxList::erase(iterator where)
{
return data_.erase(where);
}
BoxList::iterator BoxList::erase(iterator begin, iterator end)
{
return data_.erase(begin, end);
}
Box::Orientation Box::default_orientation_ = Box::Vertical;
Box::Packing Box::default_packing_ = Box::Shrink;
Box::Box(dimension_t min_w, dimension_t min_h)
: visible_(false),
min_w_(min_w),
min_h_(min_h),
w_(min_w),
h_(min_h),
x_(0),
y_(0),
orientation_(default_orientation_),
packing_(default_packing_),
prefered_visibility_(Visible)
{}
void Box::setMinimumDimensions(dimension_t min_w, dimension_t min_h)
{
min_w_ = min_w;
min_h_ = min_h;
}
Box::Orientation Box::orientation() const
{
return orientation_;
}
void Box::set(Orientation o)
{
orientation_ = o;
}
Box::Orientation Box::defaultOrientation()
{
return default_orientation_;
}
void Box::setDefault(Orientation o)
{
default_orientation_ = o;
}
Box::Packing Box::packing() const
{
return packing_;
}
void Box::set(Packing p)
{
packing_ = p;
}
Box::Packing Box::defaultPacking()
{
return default_packing_;
}
void Box::setDefault(Packing p)
{
default_packing_ = p;
}
bool Box::expandable() const
{
if (!visible_)
return false;
if (packing_ == Expand)
return true;
BoxList::const_iterator it = children_.begin();
BoxList::const_iterator const end = children_.end();
for (; it != end; ++it) {
if (it->visible() && it->packing() == Expand)
return true;
}
return false;
}
Box::PreferedVisibility Box::preferedVisibility() const
{
return prefered_visibility_;
}
void Box::set(PreferedVisibility pv)
{
prefered_visibility_ = pv;
if (pv == Invisible)
hide();
}
bool Box::visible() const
{
return visible_;
}
void Box::show()
{
if (prefered_visibility_ == Invisible)
return;
visible_ = true;
BoxList::iterator it = children_.begin();
BoxList::iterator const end = children_.end();
for (; it != end; ++it)
it->show();
}
void Box::hide()
{
visible_ = false;
BoxList::iterator it = children_.begin();
BoxList::iterator const end = children_.end();
for (; it != end; ++it)
it->hide();
}
BoxList & Box::children()
{
return children_;
}
BoxList const & Box::children() const
{
return children_;
}
Box::dimension_t Box::width() const
{
return w_;
}
Box::dimension_t Box::height() const
{
return h_;
}
Box::dimension_t Box::xorigin() const
{
return x_;
}
Box::dimension_t Box::yorigin() const
{
return y_;
}
void Box::updateMetrics()
{
shrinkMetrics();
expandMetrics(x_, y_, w_, h_);
}
void Box::shrinkMetrics()
{
dimension_t width = 0;
dimension_t height = 0;
BoxList::iterator it = children_.begin();
BoxList::iterator const end = children_.end();
for (; it != end; ++it) {
if (!it->visible())
continue;
it->shrinkMetrics();
dimension_t child_width = it->width();
dimension_t child_height = it->height();
if (orientation_ == Horizontal) {
width += child_width;
height = std::max(height, child_height);
} else {
width = std::max(width, child_width);
height += child_height;
}
}
w_ = visible_ ? std::max(min_w_, width) : 0;
h_ = visible_ ? std::max(min_h_, height) : 0;
}
void Box::expandMetrics(dimension_t x_in, dimension_t y_in,
dimension_t w_avail, dimension_t h_avail)
{
x_ = x_in;
y_ = y_in;
w_ = w_avail;
h_ = h_avail;
if (orientation_ == Vertical)
expandVbox(x_in, y_in, w_avail, h_avail);
else
expandHbox(x_in, y_in, w_avail, h_avail);
}
void Box::expandHbox(dimension_t x_in, dimension_t y_in,
dimension_t w_avail, dimension_t h_avail)
{
int nvisible_children = 0;
int nexpanded_children = 0;
dimension_t w_fixed = 0;
BoxList::const_iterator cit = children_.begin();
BoxList::const_iterator const cend = children_.end();
for (; cit != cend; ++cit) {
if (cit->visible()) {
nvisible_children += 1;
if (cit->expandable())
nexpanded_children += 1;
else
w_fixed += cit->width();
}
}
if (nvisible_children == 0)
return;
dimension_t width = 0;
dimension_t extra = 0;
if (nexpanded_children > 0) {
width = w_avail - w_fixed;
extra = width / nexpanded_children;
}
dimension_t x_child = x_in;
dimension_t y_child = y_in;
dimension_t h_child = h_avail;
BoxList::iterator it = children_.begin();
BoxList::iterator const end = children_.end();
for (; it != end; ++it) {
if (!it->visible())
continue;
dimension_t w_child = it->width();
if (it->expandable()) {
if (nexpanded_children == 1)
w_child = std::max(w_child, width);
else
w_child = std::max(w_child, extra);
nexpanded_children -= 1;
width -= w_child;
}
it->expandMetrics(x_child, y_child, w_child, h_child);
x_child += w_child;
}
}
void Box::expandVbox(dimension_t x_in, dimension_t y_in,
dimension_t w_avail, dimension_t h_avail)
{
int nvisible_children = 0;
int nexpanded_children = 0;
dimension_t h_fixed = 0;
BoxList::const_iterator cit = children_.begin();
BoxList::const_iterator const cend = children_.end();
for (; cit != cend; ++cit) {
if (cit->visible()) {
nvisible_children += 1;
if (cit->expandable())
nexpanded_children += 1;
else
h_fixed += cit->height();
}
}
if (nvisible_children == 0)
return;
dimension_t height = 0;
dimension_t extra = 0;
if (nexpanded_children > 0) {
height = h_avail - h_fixed;
extra = height / nexpanded_children;
}
dimension_t x_child = x_in;
dimension_t y_child = y_in;
dimension_t w_child = w_avail;
BoxList::iterator it = children_.begin();
BoxList::iterator const end = children_.end();
for (; it != end; ++it) {
if (!it->visible())
continue;
dimension_t h_child = it->height();
if (it->expandable()) {
if (nexpanded_children == 1)
h_child = std::max(h_child, height);
else
h_child = std::max(h_child, extra);
nexpanded_children -= 1;
height -= h_child;
}
it->expandMetrics(x_child, y_child, w_child, h_child);
y_child += h_child;
}
}
Box & WidgetMap::add(FL_OBJECT * ob, BoxList & container,
dimension_t min_w, dimension_t min_h)
{
Box & box = container.push_back(Box(min_w, min_h));
widgets_[ob] = &box;
return box;
}
void WidgetMap::updateMetrics() const
{
DataMap::const_iterator it = widgets_.begin();
DataMap::const_iterator const end = widgets_.end();
for (; it != end; ++it) {
FL_OBJECT * ob = it->first;
Box & box = *it->second;
fl_set_object_geometry(ob,
box.xorigin(), box.yorigin(),
box.width(), box.height());
}
}
Box & embed(FL_OBJECT * ob, BoxList & container, WidgetMap & widgets, int bw)
{
container.push_back(Box(0, bw));
Box & middle = container.push_back(Box(0, 0));
middle.set(Box::Horizontal);
container.push_back(Box(0, bw));
middle.children().push_back(Box(bw, 0));
Box & center = widgets.add(ob, middle.children(), 0, 0);
middle.children().push_back(Box(bw, 0));
return center;
}
} // namespace frontend
} // namespace lyx

View File

@ -0,0 +1,189 @@
// -*- C++ -*-
/**
* \file LayoutEngine.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Angus Leeming
*
* Full author contact details are available in file CREDITS.
*
* A generic layout engine that draws heavily on GTK+.
*/
#ifndef LAYOUT_ENGINE_H
#define LAYOUT_ENGINE_H
#include "forms_fwd.h"
#include <list>
#include <map>
namespace lyx {
namespace frontend {
class Box;
class BoxList {
public:
typedef std::list<Box> Container;
typedef Container::size_type size_type;
typedef Container::iterator iterator;
typedef Container::const_iterator const_iterator;
bool empty() const;
size_type size() const;
void clear();
Box & push_back(Box const &);
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
iterator erase(iterator where);
iterator erase(iterator begin, iterator end);
private:
Container data_;
};
class Box {
public:
typedef unsigned int dimension_t;
/** \param min_w the minimum allowed width of the box.
* \param min_h the minimum allowed height of the box.
*/
Box(dimension_t min_w, dimension_t min_h);
void setMinimumDimensions(dimension_t min_w, dimension_t min_h);
/** \name Child Orientation
* The enum prescribes whether children are aligned
* horizontally or vertically.
*/
//@{
enum Orientation {
Vertical,
Horizontal
};
Orientation orientation() const;
void set(Orientation);
/// Initially set to Vertical
static Orientation defaultOrientation();
static void setDefault(Orientation);
//@}
/** \name Packing
* Do the children receive extra space when the parent grows?
*/
//@{
enum Packing {
Shrink,
Expand
};
Packing packing() const;
void set(Packing);
/// Initially set to Shrink
static Packing defaultPacking();
static void setDefault(Packing);
/** returns true if this Box or any of its children have
* packing() == Expand.
*/
bool expandable() const;
//@}
/** \name Prefered Visibility
* If the parent container is visible, should this Box be
* visible or not?
*/
//@{
enum PreferedVisibility {
Visible,
Invisible
};
PreferedVisibility preferedVisibility() const;
/// If \pv == Invisible, also calls hide().
void set(PreferedVisibility pv);
//@}
/** \name Actual Visibility
*/
//@{
bool visible() const;
/// Does nothing if preferedVisibility() == Invisible.
void show();
/// Always hides.
void hide();
//@}
BoxList & children();
BoxList const & children() const;
dimension_t width() const;
dimension_t height() const;
dimension_t xorigin() const;
dimension_t yorigin() const;
void updateMetrics();
private:
void shrinkMetrics();
void expandMetrics(dimension_t x, dimension_t y,
dimension_t w, dimension_t h);
void expandHbox(dimension_t x, dimension_t y,
dimension_t w, dimension_t h);
void expandVbox(dimension_t x, dimension_t y,
dimension_t w, dimension_t h);
static Orientation default_orientation_;
static Packing default_packing_;
BoxList children_;
bool visible_;
dimension_t min_w_;
dimension_t min_h_;
dimension_t w_;
dimension_t h_;
dimension_t x_;
dimension_t y_;
Orientation orientation_;
Packing packing_;
PreferedVisibility prefered_visibility_;
};
class WidgetMap {
public:
typedef Box::dimension_t dimension_t;
/// \returns the just-added Box.
Box & add(FL_OBJECT * widget, BoxList & container,
dimension_t min_w, dimension_t min_h);
void updateMetrics() const;
private:
typedef std::map<FL_OBJECT *, Box *> DataMap;
DataMap widgets_;
};
/** Embed \c ob in \c container inside a border of width \c bw.
* Thereafter, hand control of its metrics to \c widgets.
* \returns the Box containing \c ob.
*/
Box & embed(FL_OBJECT * ob, BoxList & container, WidgetMap & widgets, int bw);
} // namespace frontend
} // namespace lyx
#endif // NOT LAYOUT_ENGINE_H

View File

@ -149,6 +149,8 @@ libxforms_la_SOURCES = \
FormVSpace.h \
FormWrap.C \
FormWrap.h \
LayoutEngine.C \
LayoutEngine.h \
LyXKeySymFactory.C \
LyXScreenFactory.C \
XFormsMenubar.C \

View File

@ -16,9 +16,9 @@
namespace WorkAreaFactory {
WorkArea * create(LyXView & owner, int x, int y, int w, int h)
WorkArea * create(LyXView & owner, int w, int h)
{
return new XWorkArea(owner, x, y, w, h);
return new XWorkArea(owner, w, h);
}
}

View File

@ -23,8 +23,13 @@
#include "support/lstrings.h"
#include "support/tostr.h"
#include <boost/bind.hpp>
#include "lyx_forms.h"
using lyx::frontend::Box;
using lyx::frontend::BoxList;
using lyx::support::lowercase;
using lyx::support::subst;
@ -82,8 +87,14 @@ extern "C" {
XFormsMenubar::XFormsMenubar(LyXView * view, MenuBackend const & mb)
: owner_(static_cast<XFormsView*>(view)), menubackend_(&mb)
: owner_(static_cast<XFormsView*>(view)),
menubackend_(&mb),
menubar_(0)
{
using lyx::frontend::WidgetMap;
owner_->metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics,
&widgets_));
makeMenubar(menubackend_->getMenubar());
}
@ -94,16 +105,27 @@ XFormsMenubar::~XFormsMenubar()
void XFormsMenubar::makeMenubar(Menu const & menu)
{
FL_FORM * form = owner_->getForm();
int moffset = 0;
// Draw a frame around the whole.
BoxList & boxlist = owner_->getBox(XFormsView::Top).children();
// Create menu frame if there is non yet.
FL_OBJECT * frame = fl_add_frame(FL_UP_FRAME, 0, 0,
form->w, mheight, "");
FL_OBJECT * frame = fl_add_frame(FL_UP_FRAME, 0, 0, 0, 0, "");
fl_set_object_resize(frame, FL_RESIZE_ALL);
fl_set_object_gravity(frame, NorthWestGravity,
NorthEastGravity);
fl_set_object_gravity(frame, NorthWestGravity, NorthEastGravity);
menubar_ = &widgets_.add(frame, boxlist, 0, mheight);
// The menubar contains three vertically-aligned Boxes,
// the center one of which is to contain the buttons,
// aligned horizontally.
// The other two provide some visual padding.
menubar_->children().push_back(Box(0, yloc));
Box & menubar_center = menubar_->children().push_back(Box(0,0));
menubar_center.set(Box::Horizontal);
menubar_->children().push_back(Box(0, yloc));
BoxList & menubar_buttons = menubar_center.children();
// Add the buttons.
Menu::const_iterator i = menu.begin();
Menu::const_iterator end = menu.end();
for (; i != end; ++i) {
@ -117,11 +139,12 @@ void XFormsMenubar::makeMenubar(Menu const & menu)
string const label = i->label();
string const shortcut = '#' + i->shortcut();
int const width = string_width(label);
obj = fl_add_button(FL_MENU_BUTTON,
air + moffset, yloc,
width + mbadd,
mbheight,
label.c_str());
obj = fl_add_button(FL_MENU_BUTTON, 0, 0, 0, 0, label.c_str());
menubar_buttons.push_back(Box(air, 0));
widgets_.add(obj, menubar_buttons, width + mbadd, mbheight);
fl_set_object_boxtype(obj, FL_FLAT_BOX);
fl_set_object_color(obj, FL_MCOL, FL_MCOL);
fl_set_object_lsize(obj, MENU_LABEL_SIZE);
@ -129,7 +152,6 @@ void XFormsMenubar::makeMenubar(Menu const & menu)
fl_set_object_resize(obj, FL_RESIZE_ALL);
fl_set_object_gravity(obj, NorthWestGravity,
NorthWestGravity);
moffset += obj->w + air;
fl_set_object_shortcut(obj, shortcut.c_str(), 1);
fl_set_object_callback(obj, C_XFormsMenubar_MenuCallback, 1);
@ -138,7 +160,6 @@ void XFormsMenubar::makeMenubar(Menu const & menu)
buttonlist_.push_back(iteminfo);
obj->u_vdata = iteminfo.get();
}
}

View File

@ -15,6 +15,8 @@
#include "funcrequest.h"
#include "frontends/Menubar.h"
#include "LayoutEngine.h"
#include <boost/shared_ptr.hpp>
#include "forms_fwd.h"
@ -67,6 +69,10 @@ private:
///
MenuBackend const * menubackend_;
///
lyx::frontend::Box * menubar_;
///
lyx::frontend::WidgetMap widgets_;
///
struct ItemInfo {
///
ItemInfo(XFormsMenubar * p, MenuItem const * i,

View File

@ -30,6 +30,11 @@
#include "lyx_forms.h"
#include "combox.h"
#include <boost/bind.hpp>
using lyx::frontend::Box;
using lyx::frontend::BoxList;
using std::distance;
using std::endl;
using std::string;
@ -90,10 +95,17 @@ XFormsToolbar::toolbarItem::operator=(toolbarItem const & ti)
XFormsToolbar::XFormsToolbar(LyXView * o, int x, int y)
: owner_(static_cast<XFormsView *>(o)), combox_(0), xpos(x), ypos(y)
XFormsToolbar::XFormsToolbar(LyXView * o)
: toolbar_(0),
toolbar_buttons_(0),
owner_(static_cast<XFormsView *>(o)),
combox_(0)
{
tooltip_ = new Tooltips;
using lyx::frontend::WidgetMap;
owner_->metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics,
&widgets_));
}
@ -278,6 +290,23 @@ void XFormsToolbar::add(ToolbarBackend::Toolbar const & tb)
if (!toollist_.empty())
return;
// The toolbar contains three vertically-aligned Boxes,
// the center one of which is to contain the buttons,
// aligned horizontally.
// The other two provide some visual padding.
BoxList & boxlist = owner_->getBox(XFormsView::Top).children();
toolbar_ = &boxlist.push_back(Box(0,0));
int const padding = 2 + abs(fl_get_border_width());
toolbar_->children().push_back(Box(0, padding));
Box & toolbar_center = toolbar_->children().push_back(Box(0,0));
toolbar_center.set(Box::Horizontal);
toolbar_buttons_ = &toolbar_center.children();
toolbar_->children().push_back(Box(0, padding));
// Add the buttons themselves.
funcs.clear();
ToolbarBackend::item_iterator it = tb.items.begin();
@ -294,18 +323,21 @@ void XFormsToolbar::add(FuncRequest const & func, string const & tooltip)
switch (func.action) {
case ToolbarBackend::SEPARATOR:
xpos += sepspace;
toolbar_buttons_->push_back(Box(sepspace, 0));
break;
case ToolbarBackend::MINIBUFFER:
// Not implemented
break;
case ToolbarBackend::LAYOUTS:
xpos += standardspacing;
toolbar_buttons_->push_back(Box(standardspacing, 0));
if (combox_)
break;
combox_ = fl_add_combox(FL_DROPLIST_COMBOX,
xpos, ypos, 135, height, "");
0, 0, 135, height, "");
widgets_.add(combox_, *toolbar_buttons_, 135, height);
fl_set_combox_browser_height(combox_, 400);
fl_set_object_boxtype(combox_, FL_DOWN_BOX);
fl_set_object_color(combox_, FL_MCOL, FL_MCOL);
@ -314,17 +346,17 @@ void XFormsToolbar::add(FuncRequest const & func, string const & tooltip)
combox_->u_vdata = this;
fl_set_object_callback(combox_, C_layoutSelectedCB, 0);
xpos += 135;
break;
default: {
FL_OBJECT * obj;
xpos += standardspacing;
toolbar_buttons_->push_back(Box(standardspacing, 0));
item.icon = obj =
fl_add_pixmapbutton(FL_NORMAL_BUTTON,
xpos, ypos,
buttonwidth,
height, "");
0, 0, 0, 0, "");
widgets_.add(obj, *toolbar_buttons_, buttonwidth, height);
fl_set_object_resize(obj, FL_RESIZE_ALL);
fl_set_object_gravity(obj,
NorthWestGravity,
@ -343,14 +375,6 @@ void XFormsToolbar::add(FuncRequest const & func, string const & tooltip)
string const xpm = toolbarbackend.getIcon(func);
fl_set_pixmapbutton_file(obj, xpm.c_str());
// we must remember to update the positions
xpos += buttonwidth;
// ypos is constant
/* Here will come a check to see if the new
* pos is within the bounds of the main frame,
* and perhaps wrap the toolbar if not.
*/
break;
}
}

View File

@ -16,6 +16,8 @@
#include <vector>
#include "forms_fwd.h"
#include "LayoutEngine.h"
#include "frontends/Toolbar.h"
#include "ToolbarBackend.h"
@ -27,7 +29,7 @@ class Tooltips;
class XFormsToolbar : public Toolbar {
public:
/// create an empty toolbar
XFormsToolbar(LyXView * o, int x, int y);
XFormsToolbar(LyXView * o);
///
~XFormsToolbar();
@ -73,6 +75,13 @@ public:
FL_OBJECT * icon;
};
///
lyx::frontend::Box * toolbar_;
///
lyx::frontend::BoxList * toolbar_buttons_;
///
lyx::frontend::WidgetMap widgets_;
typedef std::vector<FuncRequest> Funcs;
Funcs funcs;
@ -87,10 +96,6 @@ public:
Tooltips * tooltip_;
/// layout combo
FL_OBJECT * combox_;
/// x position of end of toolbar
int xpos;
/// y position of end of toolbar
int ypos;
};
#endif

View File

@ -27,6 +27,8 @@
#include <boost/bind.hpp>
using lyx::frontend::Box;
using lyx::support::LibFileSearch;
using std::abs;
@ -48,13 +50,80 @@ int C_XFormsView_atCloseMainFormCB(FL_FORM * form, void * p)
}
void print_metrics(std::ostream & os, std::string const & name, Box const & box)
{
os << name << " metrics:"
<< "\tx = " << box.xorigin()
<< "\ty = " << box.yorigin()
<< "\tw = " << box.width()
<< "\th = " << box.height() << '\n';
}
XFormsView::XFormsView(int width, int height)
: LyXView(),
window_(Box(width, height)),
icon_pixmap_(0), icon_mask_(0)
{
create_form_form_main(width, height);
fl_set_form_atclose(getForm(), C_XFormsView_atCloseMainFormCB, 0);
int const air = 2;
// Logical layout of the boxes making up the LyX window.
Box & top = window_.children().push_back(Box(0,0));
Box & middle = window_.children().push_back(Box(0,0));
middle.set(Box::Horizontal);
Box & bottom = window_.children().push_back(Box(0,0));
Box & left = middle.children().push_back(Box(air,0));
Box & center = middle.children().push_back(Box(0,0));
center.set(Box::Expand);
Box & right = middle.children().push_back(Box(air,0));
// Define accessors to the various boxes.
box_map_[Top] = &top;
box_map_[Bottom] = &bottom;
box_map_[Left] = &left;
box_map_[Center] = &center;
box_map_[Right] = &right;
// Define the XForms components making up the window.
// Each uses the layout engine defined above to control its
// dimensions.
form_ = fl_bgn_form(FL_NO_BOX, width, height);
form_->u_vdata = this;
fl_set_form_atclose(form_, C_XFormsView_atCloseMainFormCB, 0);
FL_OBJECT * obj = fl_add_box(FL_FLAT_BOX, 0, 0, width, height, "");
fl_set_object_color(obj, FL_MCOL, FL_MCOL);
menubar_.reset(new XFormsMenubar(this, menubackend));
toolbar_.reset(new XFormsToolbar(this));
toolbar_->init();
bufferview_.reset(new BufferView(this, width, height));
minibuffer_.reset(new XMiniBuffer(*this, *controlcommand_));
// Assign an icon to the main form.
string const iconname = LibFileSearch("images", "lyx", "xpm");
if (!iconname.empty()) {
unsigned int w, h;
icon_pixmap_ = fl_read_pixmapfile(fl_root,
iconname.c_str(),
&w,
&h,
&icon_mask_,
0,
0,
0);
fl_set_form_icon(form_, icon_pixmap_, icon_mask_);
}
fl_end_form();
// Update the layout so that all widgets fit.
window_.show();
updateMetrics();
view_state_con =
view_state_changed.connect(boost::bind(&XFormsView::show_view_state, this));
focus_con =
@ -78,6 +147,14 @@ XFormsView::~XFormsView()
}
Box & XFormsView::getBox(Position pos) const
{
std::map<Position, Box *>::const_iterator it = box_map_.find(pos);
BOOST_ASSERT(it != box_map_.end());
return *it->second;
}
/// Redraw the main form.
void XFormsView::redraw()
{
@ -121,58 +198,16 @@ void XFormsView::show(int x, int y, string const & title)
}
void XFormsView::create_form_form_main(int width, int height)
/* to make this work as it should, .lyxrc should have been
* read first; OR maybe this one should be made dynamic.
* Hmmmm. Lgb.
* We will probably not have lyxrc before the main form is
* initialized, because error messages from lyxrc parsing
* are presented (and rightly so) in GUI popups. Asger.
*/
void XFormsView::updateMetrics()
{
// the main form
form_ = fl_bgn_form(FL_NO_BOX, width, height);
getForm()->u_vdata = this;
FL_OBJECT * obj = fl_add_box(FL_FLAT_BOX, 0, 0, width, height, "");
fl_set_object_color(obj, FL_MCOL, FL_MCOL);
window_.updateMetrics();
// Parameters for the appearance of the main form
int const air = 2;
int const bw = abs(fl_get_border_width());
FL_FORM * form = getForm();
fl_set_form_size(form, window_.width(), window_.height());
menubar_.reset(new XFormsMenubar(this, menubackend));
toolbar_.reset(new XFormsToolbar(this, air, 30 + air + bw));
toolbar_->init();
int const ywork = 60 + 2 * air + bw;
int const workheight = height - ywork - (25 + 2 * air);
bufferview_.reset(new BufferView(this, air, ywork,
width - 3 * air, workheight));
minibuffer_.reset(new XMiniBuffer(*controlcommand_,
air, height - (25 + air), width - (2 * air), 25));
// assign an icon to main form
string const iconname = LibFileSearch("images", "lyx", "xpm");
if (!iconname.empty()) {
unsigned int w, h;
icon_pixmap_ = fl_read_pixmapfile(fl_root,
iconname.c_str(),
&w,
&h,
&icon_mask_,
0,
0,
0);
fl_set_form_icon(getForm(), icon_pixmap_, icon_mask_);
}
// set min size
fl_set_form_minsize(getForm(), 50, 50);
fl_end_form();
// Emit a signal so that all daughter widgets are layed-out
// correctly.
metricsUpdated();
}

View File

@ -12,12 +12,16 @@
#ifndef LyXView_H
#define LyXView_H
#include "LayoutEngine.h"
#include "forms_fwd.h"
#include "frontends/LyXView.h"
#include <X11/Xlib.h> // for Pixmap
#include <boost/signals/signal0.hpp>
#include <map>
class XMiniBuffer;
/**
@ -27,11 +31,22 @@ class XMiniBuffer;
*/
class XFormsView : public LyXView {
public:
enum Position {
Top,
Bottom,
Left,
Right,
Center
};
/// create a main window of the given dimensions
XFormsView(int w, int h);
~XFormsView();
/// Accessor to the appropriate layout Box.
lyx::frontend::Box & getBox(Position pos) const;
/**
* show - display the top-level window
* @param xpos requested x position (or 0)
@ -56,6 +71,8 @@ public:
/// clear back to normal status message
virtual void clearMessage();
boost::signal0<void> metricsUpdated;
private:
/**
* setWindowTitle - set title of window
@ -67,8 +84,14 @@ private:
/// update the minibuffer state message
void show_view_state();
/// makes the main form.
void create_form_form_main(int width, int height);
///
void updateMetrics();
/// The top-most box of the layout engine containing all other boxes.
lyx::frontend::Box window_;
// Accessors to the various Boxes.
std::map<Position, lyx::frontend::Box *> box_map_;
/// the minibuffer
boost::scoped_ptr<XMiniBuffer> minibuffer_;
///

View File

@ -12,6 +12,7 @@
#include <config.h>
#include "XMiniBuffer.h"
#include "XFormsView.h"
#include "freebrowser.h"
#include "xforms_helpers.h"
@ -24,6 +25,9 @@
#include <boost/bind.hpp>
using lyx::frontend::Box;
using lyx::frontend::BoxList;
using lyx::frontend::WidgetMap;
using std::vector;
using std::string;
@ -32,22 +36,34 @@ using std::string;
namespace {
/// This creates the input widget for the minibuffer
FL_OBJECT * create_input_box(void * parent, int type,
FL_Coord, FL_Coord, FL_Coord, FL_Coord);
FL_OBJECT * create_input_box(void * parent, int type);
FL_FREEBROWSER * create_freebrowser(void * parent);
} // namespace anon
XMiniBuffer::XMiniBuffer(ControlCommandBuffer & control,
FL_Coord x, FL_Coord y, FL_Coord h, FL_Coord w)
XMiniBuffer::XMiniBuffer(XFormsView & owner,
ControlCommandBuffer & control)
: controller_(control),
info_shown_(false)
{
input_ = create_input_box(this, FL_NORMAL_INPUT, x, y, h, w);
input_ = create_input_box(this, FL_NORMAL_INPUT);
freebrowser_.reset(create_freebrowser(this), fl_free_freebrowser);
// The minibuffer is 25 pixels high and is embedded inside a
// 2 pixel deep frame.
int const air = 2;
BoxList & boxlist = owner.getBox(XFormsView::Bottom).children();
minibuffer_ = &boxlist.push_back(Box(0,0));
Box & center = embed(input_, minibuffer_->children(), widgets_, air);
center.set(Box::Expand);
center.setMinimumDimensions(0, 25);
owner.metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics,
&widgets_));
info_timer_.reset(new Timeout(1500));
idle_timer_.reset(new Timeout(6000));
info_con = info_timer_->timeout.connect(boost::bind(&XMiniBuffer::info_timeout, this));
@ -315,10 +331,9 @@ void C_freebrowserCB(FL_FREEBROWSER * fb, int action)
}
FL_OBJECT * create_input_box(void * parent, int type,
FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h)
FL_OBJECT * create_input_box(void * parent, int type)
{
FL_OBJECT * obj = fl_add_input(type, x, y, w, h, "");
FL_OBJECT * obj = fl_add_input(type, 0, 0, 0, 0, "");
fl_set_object_boxtype(obj, FL_DOWN_BOX);
fl_set_object_resize(obj, FL_RESIZE_ALL);
fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity);

View File

@ -16,6 +16,8 @@
#include "lyx_forms.h"
#include "LayoutEngine.h"
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/signals/connection.hpp>
@ -23,6 +25,7 @@
struct fl_freebrowser_;
typedef fl_freebrowser_ FL_FREEBROWSER;
class XFormsView;
class ControlCommandBuffer;
class Timeout;
@ -30,8 +33,7 @@ class Timeout;
class XMiniBuffer {
public:
///
XMiniBuffer(ControlCommandBuffer & control,
FL_Coord x, FL_Coord y, FL_Coord h, FL_Coord w);
XMiniBuffer(XFormsView & owner, ControlCommandBuffer & control);
///
~XMiniBuffer();
@ -102,6 +104,10 @@ private:
/// are we showing an informational temporary message ?
bool info_shown_;
///
lyx::frontend::Box * minibuffer_;
///
lyx::frontend::WidgetMap widgets_;
};
#endif // XMINIBUFFER_H

View File

@ -12,12 +12,19 @@
#include <config.h>
#include "XWorkArea.h"
#include "XFormsView.h"
#include "debug.h"
#include "XLyXKeySym.h"
#include "funcrequest.h"
#include "Timeout.h"
#include <boost/bind.hpp>
using lyx::frontend::Box;
using lyx::frontend::BoxList;
using lyx::frontend::WidgetMap;
using std::abs;
using std::dec;
using std::endl;
@ -96,25 +103,21 @@ int C_event_cb(FL_FORM * form, void * xev)
} // namespace anon
XWorkArea::XWorkArea(LyXView & owner, int x, int y, int w, int h)
XWorkArea::XWorkArea(LyXView & owner, int w, int h)
: workareapixmap(0), painter_(*this)
{
if (lyxerr.debugging(Debug::WORKAREA)) {
lyxerr << "\tbackground box: +"
<< x << '+' << y << ' '
<< w - 15 << 'x' << h << endl;
}
fl_freeze_all_forms();
FL_OBJECT * obj;
FL_OBJECT * frame;
obj = fl_add_box(FL_BORDER_BOX, x, y, w - 15, h, "");
// A frame around the work area.
frame = obj = fl_add_box(FL_BORDER_BOX, 0, 0, w, h, "");
fl_set_object_resize(obj, FL_RESIZE_ALL);
fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR,
x + w - 15, y, 17, h, "");
// The scrollbar.
scrollbar = obj = fl_add_scrollbar(FL_VERT_SCROLLBAR, 0, 0, w, h, "");
fl_set_object_boxtype(obj, FL_UP_BOX);
fl_set_object_resize(obj, FL_RESIZE_ALL);
fl_set_object_gravity(obj, NorthEastGravity, SouthEastGravity);
@ -124,24 +127,8 @@ XWorkArea::XWorkArea(LyXView & owner, int x, int y, int w, int h)
fl_set_scrollbar_value(scrollbar, 0.0);
fl_set_scrollbar_size(scrollbar, scrollbar->h);
int const bw = int(abs(fl_get_border_width()));
// Create the workarea pixmap
// FIXME remove redraw(w - 15 - 2 * bw, h - 2 * bw);
if (lyxerr.debugging(Debug::WORKAREA))
lyxerr << "\tfree object: +"
<< x + bw << '+' << y + bw << ' '
<< w - 15 - 2 * bw << 'x'
<< h - 2 * bw << endl;
// We add this object as late as possible to avoid problems
// with drawing.
// FIXME: like ??
work_area = obj = fl_add_free(FL_ALL_FREE,
x + bw, y + bw,
w - 15 - 2 * bw,
h - 2 * bw, "",
// The work area itself
work_area = obj = fl_add_free(FL_ALL_FREE, 0, 0, w, h, "",
C_work_area_handler);
obj->wantkey = FL_KEY_ALL;
obj->u_vdata = this;
@ -150,6 +137,26 @@ XWorkArea::XWorkArea(LyXView & owner, int x, int y, int w, int h)
fl_set_object_resize(obj, FL_RESIZE_ALL);
fl_set_object_gravity(obj, NorthWestGravity, SouthEastGravity);
// Hand control of the layout of these widgets to the
// Layout Engine.
XFormsView & xview = dynamic_cast<XFormsView &>(owner);
BoxList & boxlist = xview.getBox(XFormsView::Center).children();
wa_box_ = &boxlist.push_back(Box(0,0));
wa_box_->set(Box::Horizontal);
Box & frame_box = widgets_.add(frame, wa_box_->children(), 0, 0);
frame_box.set(Box::Expand);
int const bw = int(abs(fl_get_border_width()));
Box & wa_box = embed(work_area, frame_box.children(), widgets_, bw);
wa_box.set(Box::Expand);
widgets_.add(scrollbar, wa_box_->children(), 17, 0);
xview.metricsUpdated.connect(boost::bind(&WidgetMap::updateMetrics,
&widgets_));
/// X selection hook - xforms gets it wrong
fl_current_form->u_vdata = this;
fl_register_raw_callback(fl_current_form, FL_ALL_EVENT, C_event_cb);

View File

@ -16,6 +16,8 @@
#include "frontends/WorkArea.h"
#include "XPainter.h"
#include "LayoutEngine.h"
#include "lyx_forms.h"
class LyXView;
@ -24,7 +26,7 @@ class LyXView;
class XWorkArea : public WorkArea {
public:
///
XWorkArea(LyXView & owner, int xpos, int ypos, int width, int height);
XWorkArea(LyXView & owner, int width, int height);
///
~XWorkArea();
///
@ -80,6 +82,10 @@ private:
bool screen_cleared;
/// the current document's height (for scrollbar)
int doc_height_;
///
lyx::frontend::Box * wa_box_;
///
lyx::frontend::WidgetMap widgets_;
};
#endif // XWORKAREA_H