diff options
| author | MenTaLguY <mental@rydia.net> | 2006-01-16 02:36:01 +0000 |
|---|---|---|
| committer | mental <mental@users.sourceforge.net> | 2006-01-16 02:36:01 +0000 |
| commit | 179fa413b047bede6e32109e2ce82437c5fb8d34 (patch) | |
| tree | a5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/ui/widget | |
| download | inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip | |
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/ui/widget')
55 files changed, 7794 insertions, 0 deletions
diff --git a/src/ui/widget/.cvsignore b/src/ui/widget/.cvsignore new file mode 100644 index 000000000..38efca7bc --- /dev/null +++ b/src/ui/widget/.cvsignore @@ -0,0 +1,3 @@ +.deps +.dirstamp +makefile diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert new file mode 100644 index 000000000..2ef0f8f41 --- /dev/null +++ b/src/ui/widget/Makefile_insert @@ -0,0 +1,62 @@ +## Makefile.am fragment sourced by src/Makefile.am. + +ui/widget/all: ui/widget/libuiwidget.a + +ui/widget/clean: + rm -f ui/widget/libuiwidget.a $(ui_libuiwidget_a_OBJECTS) + +ui_widget_libuiwidget_a_SOURCES = \ + ui/widget/button.h \ + ui/widget/button.cpp \ + ui/widget/color-picker.cpp \ + ui/widget/color-picker.h \ + ui/widget/color-preview.cpp \ + ui/widget/color-preview.h \ + ui/widget/combo-text.cpp \ + ui/widget/combo-text.h \ + ui/widget/entity-entry.cpp \ + ui/widget/entity-entry.h \ + ui/widget/handlebox.cpp \ + ui/widget/handlebox.h \ + ui/widget/icon-widget.cpp \ + ui/widget/icon-widget.h \ + ui/widget/imageicon.cpp \ + ui/widget/imageicon.h \ + ui/widget/labelled.cpp \ + ui/widget/labelled.h \ + ui/widget/licensor.cpp \ + ui/widget/licensor.h \ + ui/widget/notebook-page.cpp \ + ui/widget/notebook-page.h \ + ui/widget/page-sizer.cpp \ + ui/widget/page-sizer.h \ + ui/widget/panel.cpp \ + ui/widget/panel.cpp \ + ui/widget/panel.h \ + ui/widget/preferences-widget.cpp \ + ui/widget/preferences-widget.h \ + ui/widget/registered-widget.cpp \ + ui/widget/registered-widget.h \ + ui/widget/registry.cpp \ + ui/widget/registry.h \ + ui/widget/ruler.cpp \ + ui/widget/ruler.h \ + ui/widget/scalar-unit.cpp \ + ui/widget/scalar-unit.h \ + ui/widget/scalar.cpp \ + ui/widget/scalar.h \ + ui/widget/selected-style.h \ + ui/widget/selected-style.cpp \ + ui/widget/style-swatch.h \ + ui/widget/style-swatch.cpp \ + ui/widget/svg-canvas.cpp \ + ui/widget/svg-canvas.h \ + ui/widget/tolerance-slider.cpp \ + ui/widget/tolerance-slider.h \ + ui/widget/toolbox.cpp \ + ui/widget/toolbox.h \ + ui/widget/unit-menu.cpp \ + ui/widget/unit-menu.h \ + ui/widget/zoom-status.h \ + ui/widget/zoom-status.cpp + diff --git a/src/ui/widget/button.cpp b/src/ui/widget/button.cpp new file mode 100644 index 000000000..19c69ba44 --- /dev/null +++ b/src/ui/widget/button.cpp @@ -0,0 +1,51 @@ +/** + * \brief Button and CheckButton widgets + * + * Author: + * buliabyak@gmail.com + * + * Copyright (C) 2005 author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "button.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +Button::Button(Glib::ustring const &label, Glib::ustring const &tooltip) + : _tooltips() +{ + set_use_underline (true); + set_label (label); + _tooltips.set_tip(*this, tooltip); +} + +CheckButton::CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip) + : _tooltips() +{ + set_use_underline (true); + set_label (label); + _tooltips.set_tip(*this, tooltip); +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/button.h b/src/ui/widget/button.h new file mode 100644 index 000000000..7e942b324 --- /dev/null +++ b/src/ui/widget/button.h @@ -0,0 +1,56 @@ +/** + * \brief Button and CheckButton widgets + * + * Author: + * buliabyak@gmail.com + * + * Copyright (C) 2005 author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_BUTTON_H +#define INKSCAPE_UI_WIDGET_BUTTON_H + +#include <gtkmm/button.h> +#include <gtkmm/checkbutton.h> +#include <gtkmm/tooltips.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Button : public Gtk::Button +{ +public: + Button(); + Button(Glib::ustring const &label, Glib::ustring const &tooltip); +protected: + Gtk::Tooltips _tooltips; +}; + +class CheckButton : public Gtk::CheckButton +{ +public: + CheckButton(); + CheckButton(Glib::ustring const &label, Glib::ustring const &tooltip); +protected: + Gtk::Tooltips _tooltips; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_BUTTON_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/color-picker.cpp b/src/ui/widget/color-picker.cpp new file mode 100644 index 000000000..9bc79ddc1 --- /dev/null +++ b/src/ui/widget/color-picker.cpp @@ -0,0 +1,167 @@ +#define __COLOR_PICKER_C__ + +/** \file + * \brief Color picker button & window + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) Authors 2000-2005 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "inkscape.h" +#include "desktop-handles.h" +#include "document.h" + +#include "ui/dialog/dialog.h" + +#include "widgets/sp-color-notebook.h" + +#include "color-picker.h" + +namespace Inkscape { + namespace UI { + namespace Widget { + +struct CPPointer { + ColorPicker *ptr; +}; + +class ColorPickerWindow : public Inkscape::UI::Dialog::Dialog { +public: + ColorPickerWindow (ColorPicker* cp, const Glib::ustring &title); + virtual ~ColorPickerWindow(); + void setRgba32 (guint32); + + SPColorSelector *_csel; + CPPointer _cpp; +}; + +ColorPicker::ColorPicker (const Glib::ustring& title, const Glib::ustring& tip, + guint32 rgba, bool undo) +: _preview(rgba), _window(0), + _title(title), _rgba(rgba), _undo(undo) +{ + set_relief (Gtk::RELIEF_NONE); + _preview.show(); + add (_preview); + _tt.set_tip (*this, tip); +} + +ColorPicker::~ColorPicker() +{ + closeWindow(); +} + +void +ColorPicker::setRgba32 (guint32 rgba) +{ + _preview.setRgba32 (rgba); + _rgba = rgba; + if (_window) + _window->setRgba32 (rgba); +} + +void +ColorPicker::closeWindow() +{ + if (_window) + { + delete _window; + _window = 0; + } +} + +void +ColorPicker::on_clicked() +{ + static int _x, _y; + if (_window) + { + _window->move(_x,_y); + _window->present(); + return; + } + + _window =new ColorPickerWindow (this, _title); + _window->setRgba32 (_rgba); + _window->show_all(); + _window->get_position (_x, _y); +} + +void +ColorPicker::on_changed (guint32) +{ +} + +void +sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp) +{ + SPColor color; + float alpha; + csel->base->getColorAlpha(color, &alpha); + guint32 rgba = sp_color_get_rgba32_falpha(&color, alpha); + + ColorPicker *ptr = static_cast<CPPointer*>((void*)cp)->ptr; + + (ptr->_preview).setRgba32 (rgba); + + if (ptr->_undo && SP_ACTIVE_DESKTOP) + sp_document_done(SP_DT_DOCUMENT(SP_ACTIVE_DESKTOP)); + + ptr->on_changed (rgba); + ptr->_changed_signal.emit (rgba); +} + +//============================================================== + +ColorPickerWindow::ColorPickerWindow (ColorPicker *cp, const Glib::ustring &title) + : Dialog("dialogs.colorpickerwindow") +{ + set_title (title); + set_border_width (4); + _csel = (SPColorSelector*)sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK, + SP_COLORSPACE_TYPE_UNKNOWN); + get_vbox()->pack_start (*Glib::wrap(&_csel->vbox), true, true, 0); + + _cpp.ptr = cp; + g_signal_connect(G_OBJECT(_csel), "dragged", + G_CALLBACK(sp_color_picker_color_mod), &_cpp); + g_signal_connect(G_OBJECT(_csel), "changed", + G_CALLBACK(sp_color_picker_color_mod), &_cpp); + + show(); +} + +ColorPickerWindow::~ColorPickerWindow() +{ + _csel = 0; +} + +void +ColorPickerWindow::setRgba32 (guint32 rgba) +{ + if (_csel) + { + SPColor color; + sp_color_set_rgb_rgba32(&color, rgba); + _csel->base->setColorAlpha(color, SP_RGBA32_A_F(rgba)); + } +} + +}}} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/color-picker.h b/src/ui/widget/color-picker.h new file mode 100644 index 000000000..adff8181a --- /dev/null +++ b/src/ui/widget/color-picker.h @@ -0,0 +1,65 @@ +#ifndef __COLOR_PICKER_H__ +#define __COLOR_PICKER_H__ + +/** + * \file Color picker button \& window. + */ +/* + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) Authors 2000-2005 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <sigc++/sigc++.h> +#include <gtkmm/button.h> +#include <gtkmm/tooltips.h> +#include "ui/widget/color-preview.h" + +class SPColorSelector; +namespace Inkscape { + namespace UI { + namespace Widget { + class ColorPickerWindow; + +class ColorPicker : public Gtk::Button { +public: + ColorPicker (const Glib::ustring& title, const Glib::ustring& tip, const guint32 rgba, bool undo); + virtual ~ColorPicker(); + void setRgba32 (guint32 rgba); + void closeWindow(); + sigc::connection connectChanged (const sigc::slot<void,guint>& slot) + { return _changed_signal.connect (slot); } + +protected: + friend void sp_color_picker_color_mod(SPColorSelector *csel, GObject *cp); + virtual void on_clicked(); + virtual void on_changed (guint32); + + ColorPreview _preview; + Gtk::Tooltips _tt; + ColorPickerWindow *_window; + + const Glib::ustring _title; + sigc::signal<void,guint32> _changed_signal; + guint32 _rgba; + bool _undo; +}; + +}}} + +#endif /* !__COLOR_PICKER_H__ */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp new file mode 100644 index 000000000..6e9f9ff4a --- /dev/null +++ b/src/ui/widget/color-preview.cpp @@ -0,0 +1,122 @@ +/** \file + * Implemenmtation of a simple color preview widget + * + * Author: + * Lauris Kaplinski <lauris@kaplinski.com> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2001-2005 Authors + * Copyright (C) 2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "display/nr-plain-stuff-gdk.h" +#include "color-preview.h" + +#define SPCP_DEFAULT_WIDTH 32 +#define SPCP_DEFAULT_HEIGHT 11 + +namespace Inkscape { + namespace UI { + namespace Widget { + +ColorPreview::ColorPreview (guint32 rgba) +{ + _rgba = rgba; + set_flags (Gtk::NO_WINDOW); +} + +void +ColorPreview::on_size_request (Gtk::Requisition *req) +{ + req->width = SPCP_DEFAULT_WIDTH; + req->height = SPCP_DEFAULT_HEIGHT; +} + +void +ColorPreview::on_size_allocate (Gtk::Allocation &all) +{ + set_allocation (all); + if (is_drawable()) + queue_draw(); +} + +bool +ColorPreview::on_expose_event (GdkEventExpose *event) +{ + if (is_drawable()) + paint (&event->area); + + return true; +} + +void +ColorPreview::setRgba32 (guint32 rgba) +{ + _rgba = rgba; + + if (is_drawable()) + queue_draw(); +} + +void +ColorPreview::paint (GdkRectangle *area) +{ + GdkRectangle warea, carea; + GdkRectangle wpaint, cpaint; + gint w2; + + const Gtk::Allocation& allocation = get_allocation(); + warea.x = allocation.get_x(); + warea.y = allocation.get_y(); + warea.width = allocation.get_width(); + warea.height = allocation.get_height(); + + if (!gdk_rectangle_intersect (area, &warea, &wpaint)) + return; + + /* Transparent area */ + + w2 = warea.width / 2; + + carea.x = warea.x; + carea.y = warea.y; + carea.width = w2; + carea.height = warea.height; + + if (gdk_rectangle_intersect (area, &carea, &cpaint)) { + nr_gdk_draw_rgba32_solid (get_window()->gobj(), + get_style()->get_black_gc()->gobj(), + cpaint.x, cpaint.y, + cpaint.width, cpaint.height, + _rgba); + } + + /* Solid area */ + + carea.x = warea.x + w2; + carea.y = warea.y; + carea.width = warea.width - w2; + carea.height = warea.height; + + if (gdk_rectangle_intersect (area, &carea, &cpaint)) { + nr_gdk_draw_rgba32_solid (get_window()->gobj(), + get_style()->get_black_gc()->gobj(), + cpaint.x, cpaint.y, + cpaint.width, cpaint.height, + _rgba | 0xff); + } +} + +}}} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ diff --git a/src/ui/widget/color-preview.h b/src/ui/widget/color-preview.h new file mode 100644 index 000000000..424c58665 --- /dev/null +++ b/src/ui/widget/color-preview.h @@ -0,0 +1,50 @@ +#ifndef __COLOR_PREVIEW_H__ +#define __COLOR_PREVIEW_H__ + +/** \file + * A simple color preview widget, mainly used within a picker button. + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2001-2005 Authors + * Copyright (C) 2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/eventbox.h> + +namespace Inkscape { + namespace UI { + namespace Widget { + +class ColorPreview : public Gtk::Widget { +public: + ColorPreview (guint32 rgba); + void setRgba32 (guint32 rgba); + +protected: + virtual void on_size_request (Gtk::Requisition *req); + virtual void on_size_allocate (Gtk::Allocation &all); + virtual bool on_expose_event (GdkEventExpose *event); + void paint (GdkRectangle *area); + + guint32 _rgba; +}; + +}}} + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/combo-text.cpp b/src/ui/widget/combo-text.cpp new file mode 100644 index 000000000..7706f7c29 --- /dev/null +++ b/src/ui/widget/combo-text.cpp @@ -0,0 +1,92 @@ +/* Glom + * + * Copyright (C) 2001-2004 Murray Cumming + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "combo-text.h" +#include <gtk/gtkcombobox.h> + +ComboText::ComboText() + : Gtk::ComboBox() +{ + m_model = Gtk::ListStore::create(m_text_columns); + set_model(m_model); + pack_start(m_text_columns.m_column); +} + + +ComboText::~ComboText() +{ + +} + +void ComboText::append_text(const Glib::ustring& text) +{ + gtk_combo_box_append_text(gobj(), text.c_str()); +} + +void ComboText::insert_text(int position, const Glib::ustring& text) +{ + gtk_combo_box_insert_text(gobj(), position, text.c_str()); +} + +void ComboText::prepend_text(const Glib::ustring& text) +{ + gtk_combo_box_prepend_text(gobj(), text.c_str()); +} + +Glib::ustring ComboText::get_active_text() const +{ + Glib::ustring result; + + //Get the active row: + Gtk::TreeModel::iterator active_row = get_active(); + if(active_row) + { + Gtk::TreeModel::Row row = *active_row; + result = row[m_text_columns.m_column]; + } + + return result; +} + +void ComboText::clear_text() +{ + m_model->clear(); +} + +void ComboText::set_active_text(const Glib::ustring& text) +{ + for(Gtk::TreeModel::iterator iter = m_model->children().begin(); iter != m_model->children().end(); ++iter) + { + Glib::ustring this_text = (*iter)[m_text_columns.m_column]; + + if(this_text == text) + { + set_active(iter); + return; //success + } + } + + //Not found, so mark it as blank: + unset_active(); +} diff --git a/src/ui/widget/combo-text.h b/src/ui/widget/combo-text.h new file mode 100644 index 000000000..382414fb0 --- /dev/null +++ b/src/ui/widget/combo-text.h @@ -0,0 +1,66 @@ +/* Glom + * + * Copyright (C) 2001-2004 Murray Cumming + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH +#define GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH + +#include <gtkmm/combobox.h> + +#include <gtkmm/liststore.h> + +/** This class should just derive from Gtk::ComboBoxText and provide a + * constuctor suitable for libglade's get_widget_derived() template. + * However, I have reimplemented Gtk::ComboBoxText here temporarily, + * until the fixes in gtkmm 2.4.3 are widely available. + */ +class ComboText : public Gtk::ComboBox +{ + public: + ComboText(); + virtual ~ComboText(); + + void append_text(const Glib::ustring& text); + void insert_text(int position, const Glib::ustring& text); + void prepend_text(const Glib::ustring& text); + Glib::ustring get_active_text() const; + + //This is not part of ComboBoxText: + void clear_text(); + void set_active_text(const Glib::ustring& text); + + protected: + + //Tree model columns: + //These columns are used by the model that is created by the default constructor + class TextModelColumns : public Gtk::TreeModel::ColumnRecord + { + public: + TextModelColumns() + { add(m_column); } + + Gtk::TreeModelColumn<Glib::ustring> m_column; + }; + + TextModelColumns m_text_columns; + Glib::RefPtr<Gtk::ListStore> m_model; + +}; + +#endif //GLOM_MODE_DESIGN_COMBO_TEXTGLADE_HH diff --git a/src/ui/widget/entity-entry.cpp b/src/ui/widget/entity-entry.cpp new file mode 100644 index 000000000..1b4048ab0 --- /dev/null +++ b/src/ui/widget/entity-entry.cpp @@ -0,0 +1,161 @@ +/** \file + * + * Authors: + * bulia byak <buliabyak@users.sf.net> + * Bryce W. Harrington <bryce@bryceharrington.org> + * Lauris Kaplinski <lauris@kaplinski.com> + * Jon Phillips <jon@rejon.org> + * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm) + * + * Copyright (C) 2000 - 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/entry.h> + +#include "ui/widget/registry.h" + +#include "dialogs/rdf.h" + +#include "inkscape.h" + +#include "entity-entry.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +//=================================================== + +//--------------------------------------------------- + +EntityEntry* +EntityEntry::create (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr) +{ + g_assert (ent); + EntityEntry* obj = 0; + switch (ent->format) + { + case RDF_FORMAT_LINE: + obj = new EntityLineEntry (ent, tt, wr); + break; + case RDF_FORMAT_MULTILINE: + obj = new EntityMultiLineEntry (ent, tt, wr); + break; + default: + g_warning ("Can't happen."); + } + + obj->_label.show(); + return obj; +} + +EntityEntry::EntityEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr) +: _label(Glib::ustring(_(ent->title))+":", 1.0, 0.5), _packable(0), + _entity(ent), _tt(&tt), _wr(&wr) +{ +} + +EntityEntry::~EntityEntry() +{ + _changed_connection.disconnect(); +} + +EntityLineEntry::EntityLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr) +: EntityEntry (ent, tt, wr) +{ + Gtk::Entry *e = new Gtk::Entry; + tt.set_tip (*e, _(ent->tip)); + _packable = e; + _changed_connection = e->signal_changed().connect (sigc::mem_fun (*this, &EntityLineEntry::on_changed)); +} + +EntityLineEntry::~EntityLineEntry() +{ + delete reinterpret_cast<Gtk::Entry*>(_packable); +} + +void +EntityLineEntry::update (SPDocument *doc) +{ + const char *text = rdf_get_work_entity (doc, _entity); + reinterpret_cast<Gtk::Entry*>(_packable)->set_text (text ? text : ""); +} + +void +EntityLineEntry::on_changed() +{ + if (_wr->isUpdating()) return; + + _wr->setUpdating (true); + SPDocument *doc = SP_ACTIVE_DOCUMENT; + char const *text = reinterpret_cast<Gtk::Entry*>(_packable)->get_text().c_str(); + if (rdf_set_work_entity (doc, _entity, text)) + sp_document_done (doc); + _wr->setUpdating (false); +} + +EntityMultiLineEntry::EntityMultiLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr) +: EntityEntry (ent, tt, wr) +{ + Gtk::ScrolledWindow *s = new Gtk::ScrolledWindow; + s->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + s->set_shadow_type (Gtk::SHADOW_IN); + _packable = s; + _v.set_size_request (-1, 5); + _v.set_wrap_mode (Gtk::WRAP_WORD); + _v.set_accepts_tab (false); + s->add (_v); + tt.set_tip (_v, _(ent->tip)); + _changed_connection = _v.get_buffer()->signal_changed().connect (sigc::mem_fun (*this, &EntityMultiLineEntry::on_changed)); +} + +EntityMultiLineEntry::~EntityMultiLineEntry() +{ + delete reinterpret_cast<Gtk::ScrolledWindow*>(_packable); +} + +void +EntityMultiLineEntry::update (SPDocument *doc) +{ + const char *text = rdf_get_work_entity (doc, _entity); + Gtk::ScrolledWindow *s = reinterpret_cast<Gtk::ScrolledWindow*>(_packable); + Gtk::TextView *tv = reinterpret_cast<Gtk::TextView*>(s->get_child()); + tv->get_buffer()->set_text (text ? text : ""); +} + +void +EntityMultiLineEntry::on_changed() +{ + if (_wr->isUpdating()) return; + + _wr->setUpdating (true); + SPDocument *doc = SP_ACTIVE_DOCUMENT; + Gtk::ScrolledWindow *s = reinterpret_cast<Gtk::ScrolledWindow*>(_packable); + Gtk::TextView *tv = reinterpret_cast<Gtk::TextView*>(s->get_child()); + char const *text = tv->get_buffer()->get_text().c_str(); + if (rdf_set_work_entity (doc, _entity, text)) + sp_document_done (doc); + _wr->setUpdating (false); +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/entity-entry.h b/src/ui/widget/entity-entry.h new file mode 100644 index 000000000..5bdee9a90 --- /dev/null +++ b/src/ui/widget/entity-entry.h @@ -0,0 +1,84 @@ +/** \file + * \brief + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H +#define INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H + +#include <gtkmm/textview.h> +#include <gtkmm/tooltips.h> + +struct rdf_work_entity_t; +class SPDocument; + +namespace Gtk { +class TextBuffer; +} + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Registry; + +class EntityEntry { +public: + static EntityEntry* create (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr); + virtual ~EntityEntry() = 0; + virtual void update (SPDocument *doc) = 0; + virtual void on_changed() = 0; + Gtk::Label _label; + Gtk::Widget *_packable; + +protected: + EntityEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr); + sigc::connection _changed_connection; + rdf_work_entity_t *_entity; + Gtk::Tooltips *_tt; + Registry *_wr; +}; + +class EntityLineEntry : public EntityEntry { +public: + EntityLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr); + ~EntityLineEntry(); + void update (SPDocument *doc); + +protected: + virtual void on_changed(); +}; + +class EntityMultiLineEntry : public EntityEntry { +public: + EntityMultiLineEntry (rdf_work_entity_t* ent, Gtk::Tooltips& tt, Registry& wr); + ~EntityMultiLineEntry(); + void update (SPDocument *doc); + +protected: + virtual void on_changed(); + Gtk::TextView _v; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_ENTITY_ENTRY__H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/handlebox.cpp b/src/ui/widget/handlebox.cpp new file mode 100644 index 000000000..b82b715bb --- /dev/null +++ b/src/ui/widget/handlebox.cpp @@ -0,0 +1,48 @@ +/** + * \brief HandleBox Widget - Adds a detachment handle to another widget. + * + * This work really doesn't amount to much more than a convenience constructor + * for Gtk::HandleBox. Maybe this could be contributed back to Gtkmm, as + * Gtkmm provides several convenience constructors for other widgets as well. + * + * Author: + * Derek P. Moore <derekm@hackunix.org> + * + * Copyright (C) 2004 Derek P. Moore + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "handlebox.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +HandleBox::HandleBox(Gtk::Widget *widget, + Gtk::PositionType position) + : _widget(widget) +{ + g_assert(_widget != NULL); + add(*Gtk::manage(_widget)); + set_handle_position(position); +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/handlebox.h b/src/ui/widget/handlebox.h new file mode 100644 index 000000000..41a993e9d --- /dev/null +++ b/src/ui/widget/handlebox.h @@ -0,0 +1,50 @@ +/** + * \brief HandleBox Widget - Adds a detachment handle to another widget. + * + * This work really doesn't amount to much more than a convenience constructor + * for Gtk::HandleBox. Maybe this could be contributed back to Gtkmm, as + * Gtkmm provides several convenience constructors for other widgets as well. + * + * Author: + * Derek P. Moore <derekm@hackunix.org> + * + * Copyright (C) 2004 Derek P. Moore + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_HANDLEBOX_H +#define INKSCAPE_UI_WIDGET_HANDLEBOX_H + +#include <gtkmm/handlebox.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +class HandleBox : public Gtk::HandleBox +{ +public: + HandleBox(Gtk::Widget *widget, + Gtk::PositionType position = Gtk::POS_LEFT); + +protected: + Gtk::Widget *_widget; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_HANDLEBOX_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/icon-widget.cpp b/src/ui/widget/icon-widget.cpp new file mode 100644 index 000000000..c456778b6 --- /dev/null +++ b/src/ui/widget/icon-widget.cpp @@ -0,0 +1,165 @@ +/** + * \brief Icon Widget + * + * Author: + * Bryce Harrington <bryce@bryceharrington.org> + * + * Copyright (C) 2004 Bryce Harrington + * based on work by Lauris Kaplinski in 2002 released under GPL + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "icon-widget.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * General purpose icon widget, supporting SVG, etc. icon loading + * + * \param ... + * + * An icon widget is a ... + */ + +IconWidget::IconWidget() +{ + _pb = NULL; + _size = 0; +} + +IconWidget::IconWidget(int unsigned size, int unsigned scale, gchar const *name) +{ + _size = std::max((int unsigned)128, std::min(size, (int unsigned)1)); + + char c[256]; + g_snprintf (c, 256, "%d:%d:%s", _size, scale, name); + guchar *pixels = image_load_gtk(name, _size, scale); + + if (pixels == NULL) { + g_warning("Couldn't find matching icon for %s - has this application been installed?", name); + _pb = NULL; + } else { + /* TODO + _pb = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, + TRUE, 8, _size, _size, _size * 4, + (GdkPixbufDestroyNotify)nr_free, NULL); + */ + } +} + +IconWidget::IconWidget(int unsigned size, guchar const *px) +{ + _size = std::max((int unsigned)128, std::min(size, (int unsigned)1)); + + /* + _pb = gdk_pixbuf_new_from_data((guchar *)px, GDK_COLORSPACE_RGB, + TRUE, 8, _size, _size, _size * 4, NULL, NULL); + */ +} + +IconWidget::~IconWidget() { +} + +void IconWidget::size_request(Gtk::Requisition &requisition) +{ + requisition.width = _size; + requisition.height = _size; +} + +void IconWidget::size_allocate(Gtk::Allocation const &allocation) +{ + Gtk::Widget::size_allocate(allocation); + + if (this->is_drawable()) { + this->queue_draw(); + } +} + +int IconWidget::expose(GdkEventExpose *event) +{ + if (this->is_drawable()) { + paint(&(event->area)); + } + return true; +} + +void IconWidget::paint(GdkRectangle const *area) +{ + Gtk::Allocation allocation = get_allocation(); + int const x_pad = std::max(0, (allocation.get_width() - _size)/2); + int const y_pad = std::max(0, (allocation.get_height() - _size)/2); + + int const x_max = std::max(area->x, allocation.get_x() + x_pad); + int const y_max = std::max(area->y, allocation.get_y() + y_pad); + int const x_min = std::min(area->x + area->width, + allocation.get_x() + x_pad + _size); + int const y_min = std::min(area->y + area->height, + allocation.get_y() + y_pad + _size); + + if (_pb) { + gdk_draw_pixbuf(this->get_window()->gobj(), NULL, _pb, + x_max - allocation.get_x() - x_pad, + y_max - allocation.get_y() - y_pad, + x_max, y_max, + x_min - x_max, y_min - y_max, + GDK_RGB_DITHER_NORMAL, x_max, y_max); + } +} + +guchar* IconWidget::image_load(gchar const *name, int unsigned size, int unsigned scale) +{ + guchar *px; + + if (_do_bitmap_icons) { + px = image_load_pixmap(name, size, scale); + if (!px) { + px = image_load_svg(name, size, scale); + } + } else { + px = image_load_svg(name, size, scale); + if (!px) { + px = image_load_pixmap(name, size, scale); + } + } + return px; +} + +guchar* IconWidget::image_load_pixmap(gchar const *name, int unsigned size, int unsigned scale) +{ + // TODO + return NULL; +} + +guchar* IconWidget::image_load_svg(gchar const *name, int unsigned size, int unsigned scale) +{ + // TODO + return NULL; +} + +guchar* IconWidget::image_load_gtk(gchar const *name, int unsigned size, int unsigned scale) +{ + // TODO + return NULL; +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/icon-widget.h b/src/ui/widget/icon-widget.h new file mode 100644 index 000000000..3ca461b33 --- /dev/null +++ b/src/ui/widget/icon-widget.h @@ -0,0 +1,63 @@ +/** + * \brief Icon Widget - General image widget (including SVG icons) + * + * Author: + * Bryce Harrington <bryce@bryceharrington.org> + * + * Copyright (C) 2004 Bryce Harrington + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_UI_WIDGET_ICON_H +#define INKSCAPE_UI_WIDGET_ICON_H + +#include <gtkmm/image.h> +#include <gdkmm/rectangle.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +class IconWidget : public Gtk::Widget +{ +public: + IconWidget(); + IconWidget(int unsigned size, int unsigned scale, gchar const *name); + IconWidget(int unsigned size, guchar const *px); + virtual ~IconWidget(); + + // Overrides of Gtk::Widget functions + void size_request(Gtk::Requisition &requisition); + void size_allocate(Gtk::Allocation const &allocation); + + int expose(GdkEventExpose *event); + void paint(GdkRectangle const *area); + guchar* image_load(gchar const *name, int unsigned size, int unsigned scale); + guchar* image_load_pixmap(gchar const *name, int unsigned size, int unsigned scale); + guchar* image_load_svg(gchar const *name, int unsigned size, int unsigned scale); + guchar* image_load_gtk(gchar const *name, int unsigned size, int unsigned scale); + +protected: + int _size; + GdkPixbuf *_pb; + bool _do_bitmap_icons; +}; + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_ICON_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/imageicon.cpp b/src/ui/widget/imageicon.cpp new file mode 100644 index 000000000..6a817e30d --- /dev/null +++ b/src/ui/widget/imageicon.cpp @@ -0,0 +1,442 @@ +/* + * A simple image display widget, using Inkscape's own rendering engine + * + * Authors: + * Bob Jamison + * Other dudes from The Inkscape Organization + * + * Copyright (C) 2004 The Inkscape Organization + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + + + + +#include "imageicon.h" +#include <sys/stat.h> +#include "svg-view-widget.h" +#include "document.h" +#include "inkscape.h" + + +namespace Inkscape +{ +namespace UI +{ +namespace Widget +{ + + + +typedef enum { + SVG_TYPES, + IMPORT_TYPES, + EXPORT_TYPES + } FileDialogType; + + +/*######################################################################### +### ImageIcon widget +#########################################################################*/ + + +/** + * Constructor + */ +ImageIcon::ImageIcon() +{ + init(); +} + +/** + * Construct from a file name + */ +ImageIcon::ImageIcon(const Glib::ustring &fileName) +{ + init(); + showSvgFile(fileName); +} + +/** + * Copy Constructor + */ +ImageIcon::ImageIcon(const ImageIcon &other) + : sigc::trackable(), Glib::ObjectBase(), Gtk::VBox() +{ + init(); + document = other.document; + viewerGtkmm = other.viewerGtkmm; + showingBrokenImage = other.showingBrokenImage; +} + +/** + * Destructor + */ +ImageIcon::~ImageIcon() +{ + if (document) + sp_document_unref(document); +} + + +/** + * basic initialization, called by the various constructors + */ +void ImageIcon::init() +{ + if (!INKSCAPE) + inkscape_application_init("",false); + document = NULL; + viewerGtkmm = NULL; + //set_size_request(150,150); + showingBrokenImage = false; +} + + +bool ImageIcon::showSvgDocument(const SPDocument *docArg) +{ + + if (document) + sp_document_unref(document); + + SPDocument *doc = (SPDocument *)docArg; + + sp_document_ref(doc); + document = doc; + + //This should remove it from the box, and free resources + //if (viewerGtkmm) + // viewerGtkmm->destroy(); + + GtkWidget *viewerGtk = sp_svg_view_widget_new(doc); + viewerGtkmm = Glib::wrap(viewerGtk); + + viewerGtkmm->show(); + pack_start(*viewerGtkmm, TRUE, TRUE, 0); + + //GtkWidget *vbox = (GtkWidget *)gobj(); + //gtk_box_pack_start(GTK_BOX(vbox), viewerGtk, TRUE, TRUE, 0); + + return true; +} + +bool ImageIcon::showSvgFile(const Glib::ustring &theFileName) +{ + Glib::ustring fileName = theFileName; + + fileName = Glib::filename_to_utf8(fileName); + + SPDocument *doc = sp_document_new (fileName.c_str(), 0); + if (!doc) { + g_warning("SVGView: error loading document '%s'\n", fileName.c_str()); + return false; + } + + showSvgDocument(doc); + + sp_document_unref(doc); + + return true; +} + + + +bool ImageIcon::showSvgFromMemory(const char *xmlBuffer) +{ + if (!xmlBuffer) + return false; + + gint len = (gint)strlen(xmlBuffer); + SPDocument *doc = sp_document_new_from_mem(xmlBuffer, len, 0); + if (!doc) { + g_warning("SVGView: error loading buffer '%s'\n",xmlBuffer); + return false; + } + + showSvgDocument(doc); + + sp_document_unref(doc); + + return true; +} + + + +bool ImageIcon::showBitmap(const Glib::ustring &theFileName) +{ + Glib::ustring fileName = theFileName; + + + /*##################################### + # LET'S HAVE SOME FUN WITH SVG! + # Instead of just loading an image, why + # don't we make a lovely little svg and + # display it nicely? + #####################################*/ + + //Arbitrary size of svg doc -- rather 'portrait' shaped + gint previewWidth = 400; + gint previewHeight = 600; + + //Get some image info. Smart pointer does not need to be deleted + Glib::RefPtr<Gdk::Pixbuf> img = Gdk::Pixbuf::create_from_file(fileName); + gint imgWidth = img->get_width(); + gint imgHeight = img->get_height(); + + //Find the minimum scale to fit the image inside the preview area + double scaleFactorX = (0.9 *(double)previewWidth) / ((double)imgWidth); + double scaleFactorY = (0.9 *(double)previewHeight) / ((double)imgHeight); + double scaleFactor = scaleFactorX; + if (scaleFactorX > scaleFactorY) + scaleFactor = scaleFactorY; + + //Now get the resized values + gint scaledImgWidth = (int) (scaleFactor * (double)imgWidth); + gint scaledImgHeight = (int) (scaleFactor * (double)imgHeight); + + //center the image on the area + gint imgX = (previewWidth - scaledImgWidth) / 2; + gint imgY = (previewHeight - scaledImgHeight) / 2; + + //wrap a rectangle around the image + gint rectX = imgX-1; + gint rectY = imgY-1; + gint rectWidth = scaledImgWidth +2; + gint rectHeight = scaledImgHeight+2; + + //Our template. Modify to taste + gchar const *xformat = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<svg\n" + "xmlns=\"http://www.w3.org/2000/svg\"\n" + "xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" + "width=\"%d\" height=\"%d\">\n" + "<rect\n" + " style=\"fill:#eeeeee;stroke:none\"\n" + " x=\"-100\" y=\"-100\" width=\"4000\" height=\"4000\"/>\n" + "<image x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"\n" + "xlink:href=\"%s\"/>\n" + "<rect\n" + " style=\"fill:none;" + " stroke:#000000;stroke-width:1.0;" + " stroke-linejoin:miter;stroke-opacity:1.0000000;" + " stroke-miterlimit:4.0000000;stroke-dasharray:none\"\n" + " x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"/>\n" + "</svg>\n\n"; + + //if (!Glib::get_charset()) //If we are not utf8 + fileName = Glib::filename_to_utf8(fileName); + + //Fill in the template + /* FIXME: Do proper XML quoting for fileName. */ + gchar *xmlBuffer = g_strdup_printf(xformat, + previewWidth, previewHeight, + imgX, imgY, scaledImgWidth, scaledImgHeight, + fileName.c_str(), + rectX, rectY, rectWidth, rectHeight); + + //g_message("%s\n", xmlBuffer); + + //now show it! + showSvgFromMemory(xmlBuffer); + g_free(xmlBuffer); + + return true; +} + + + +void ImageIcon::showBrokenImage(const Glib::ustring &errorMessage) +{ + //Are we already showing it? + if (showingBrokenImage) + return; + + //Our template. Modify to taste + gchar const *xformat = + "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" + "<!-- Created with Inkscape (http://www.inkscape.org/) -->" + "<svg" + " xmlns:xml='http://www.w3.org/XML/1998/namespace'" + " xmlns:svg='http://www.w3.org/2000/svg'" + " xmlns='http://www.w3.org/2000/svg'" + " id='svg2'" + " height='64.000000'" + " width='64.000000'" + " y='0.00000000'" + " x='0.00000000'" + " version='1.0'>" + " <defs" + " id='defs3' />" + " <rect" + " id='rect1723'" + " style='fill:#fefefe;fill-opacity:1.0000000;stroke:#fe0101;stroke-opacity:1.0000000'" + " y='0.74437392'" + " x='0.52374262'" + " height='62.698864'" + " width='62.701584' />" + " <path" + " id='path1725'" + " style='fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#fe0101;stroke-width:0.99443889px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000'" + " d='M 0.35436684,0.57368969 L 62.861950,63.081272' />" + " <path" + " id='path1727'" + " style='fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#fe0101;stroke-width:0.99443889px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000'" + " d='M 0.53194379,63.258849 L 63.217104,0.92884358' />" + " <path" + " id='text1729'" + " style='font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial Black'" + " d='M 11.027113,15.116791 L 13.421921,15.116791 L 13.421921,18.076798 C 13.658875,17.828198 13.926907,17.641741 14.226014,17.517426 C 14.529009,17.393131 14.863071,17.330979 15.228229,17.330969 C 15.981815,17.330979 16.605278,17.602888 17.098629,18.146717 C 17.591951,18.686677 17.838621,19.463583 17.838631,20.477433 C 17.838621,21.153343 17.725971,21.749619 17.500671,22.266259 C 17.275361,22.779022 16.962660,23.163581 16.562557,23.419968 C 16.166333,23.672456 15.725439,23.798710 15.239874,23.798710 C 14.824228,23.798710 14.443547,23.709359 14.097831,23.530668 C 13.837556,23.390830 13.553992,23.128627 13.247118,22.744057 L 13.247118,23.658862 L 11.027113,23.658862 L 11.027113,15.116791 M 13.404438,20.547352 C 13.404438,21.079536 13.503494,21.466054 13.701606,21.706887 C 13.903597,21.943842 14.158034,22.062320 14.464918,22.062320 C 14.748482,22.062320 14.985437,21.945791 15.175782,21.712715 C 15.370006,21.475760 15.467113,21.079536 15.467123,20.524052 C 15.467113,20.034599 15.371945,19.675289 15.181610,19.446090 C 14.995153,19.216912 14.767903,19.102313 14.499872,19.102313 C 14.177455,19.102313 13.913313,19.222739 13.707434,19.463573 C 13.505433,19.700537 13.404438,20.061797 13.404438,20.547352 M 18.986502,17.470807 L 21.206507,17.470807 L 21.206507,18.484677 C 21.420152,18.045732 21.639635,17.744675 21.864935,17.581518 C 22.094123,17.414492 22.375749,17.330979 22.709820,17.330969 C 23.059425,17.330979 23.442055,17.439740 23.857701,17.657264 L 23.123527,19.347034 C 22.843831,19.230506 22.622419,19.172242 22.459271,19.172232 C 22.148509,19.172242 21.907666,19.300425 21.736752,19.556801 C 21.492021,19.918071 21.369655,20.593971 21.369665,21.584522 L 21.369665,23.658862 L 18.986502,23.658862 L 18.986502,17.470807 M 24.149042,20.582316 C 24.149042,19.638385 24.467571,18.861480 25.104638,18.251600 C 25.741695,17.637853 26.602114,17.330979 27.685903,17.330969 C 28.925063,17.330979 29.861228,17.690289 30.494417,18.408921 C 31.003281,18.987724 31.257718,19.700537 31.257728,20.547352 C 31.257718,21.499070 30.941129,22.279853 30.307960,22.889723 C 29.678659,23.495714 28.806586,23.798710 27.691730,23.798710 C 26.697291,23.798710 25.893188,23.546212 25.279440,23.041226 C 24.525835,22.415813 24.149042,21.596177 24.149042,20.582316 M 26.526367,20.576489 C 26.526367,21.128094 26.637078,21.535973 26.858500,21.800116 C 27.083800,22.064269 27.365425,22.196340 27.703385,22.196340 C 28.045214,22.196340 28.324899,22.066208 28.542443,21.805944 C 28.763855,21.545679 28.874566,21.128094 28.874566,20.553179 C 28.874566,20.017127 28.763855,19.618964 28.542443,19.358689 C 28.321021,19.094546 28.047163,18.962475 27.720867,18.962465 C 27.375141,18.962475 27.089627,19.096485 26.864327,19.364517 C 26.639017,19.628669 26.526367,20.032660 26.526367,20.576489 M 32.388127,15.116791 L 34.812072,15.116791 L 34.812072,19.521837 L 36.583416,17.470807 L 39.502631,17.470807 L 37.282626,19.638375 L 39.630824,23.658862 L 36.956330,23.658862 L 35.703566,21.176653 L 34.812072,22.050665 L 34.812072,23.658862 L 32.388127,23.658862 L 32.388127,15.116791 M 46.832739,21.153343 L 42.078078,21.153343 C 42.120799,21.534024 42.223744,21.817598 42.386891,22.004056 C 42.616080,22.272087 42.915187,22.406107 43.284223,22.406107 C 43.517290,22.406107 43.738702,22.347833 43.948479,22.231295 C 44.076662,22.157498 44.214561,22.027365 44.362175,21.840908 L 46.698719,22.056492 C 46.341337,22.678017 45.910148,23.124739 45.405172,23.396658 C 44.900176,23.664689 44.175718,23.798710 43.231777,23.798710 C 42.412140,23.798710 41.767306,23.684110 41.297285,23.454922 C 40.827253,23.221855 40.436856,22.854768 40.126104,22.353661 C 39.819220,21.848675 39.665779,21.256287 39.665779,20.576489 C 39.665779,19.609248 39.974601,18.826515 40.592247,18.228291 C 41.213762,17.630086 42.070302,17.330979 43.161858,17.330969 C 44.047525,17.330979 44.746735,17.464989 45.259497,17.733020 C 45.772250,18.001051 46.162646,18.389509 46.430688,18.898373 C 46.698709,19.407248 46.832729,20.069564 46.832739,20.885312 L 46.832739,21.153343 M 44.420439,20.017117 C 44.373820,19.558750 44.249515,19.230506 44.047525,19.032394 C 43.849413,18.834282 43.587209,18.735226 43.260914,18.735226 C 42.884111,18.735226 42.583054,18.884779 42.357764,19.183887 C 42.214028,19.370354 42.122739,19.648091 42.083906,20.017117 L 44.420439,20.017117 M 47.934001,17.470807 L 50.142351,17.470807 L 50.142351,18.478849 C 50.472535,18.067092 50.806606,17.773812 51.144556,17.599000 C 51.482507,17.420319 51.894264,17.330979 52.379838,17.330969 C 53.036317,17.330979 53.549080,17.527142 53.918116,17.919478 C 54.291021,18.307935 54.477478,18.910038 54.477488,19.725776 L 54.477488,23.658862 L 52.094325,23.658862 L 52.094325,20.256021 C 52.094325,19.867563 52.022457,19.593705 51.878731,19.434436 C 51.735004,19.271298 51.533004,19.189714 51.272750,19.189714 C 50.985287,19.189714 50.752220,19.298486 50.573530,19.516019 C 50.394839,19.733553 50.305499,20.123950 50.305499,20.687200 L 50.305499,23.658862 L 47.934001,23.658862 L 47.934001,17.470807' />" + " <path" + " id='text1733'" + " style='font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:100.00000%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Arial Black'" + " d='M 13.747801,34.415696 L 16.119299,34.415696 L 16.119299,36.029710 L 13.747801,36.029710 L 13.747801,34.415696 M 13.747801,36.769712 L 16.119299,36.769712 L 16.119299,42.957766 L 13.747801,42.957766 L 13.747801,36.769712 M 17.640095,36.769712 L 19.854272,36.769712 L 19.854272,37.672871 C 20.172801,37.296078 20.493269,37.028047 20.815696,36.868768 C 21.141991,36.709508 21.534327,36.629883 21.992704,36.629874 C 22.486035,36.629883 22.876432,36.717285 23.163894,36.892077 C 23.451337,37.066890 23.686352,37.327154 23.868931,37.672871 C 24.241836,37.268880 24.581735,36.995022 24.888619,36.851295 C 25.195493,36.703681 25.574225,36.629883 26.024845,36.629874 C 26.689090,36.629883 27.207670,36.827986 27.580595,37.224210 C 27.953500,37.616546 28.139957,38.232243 28.139967,39.071300 L 28.139967,42.957766 L 25.762641,42.957766 L 25.762641,39.432560 C 25.762631,39.152874 25.708246,38.945056 25.599484,38.809097 C 25.440214,38.595452 25.242102,38.488619 25.005157,38.488619 C 24.725462,38.488619 24.500161,38.589624 24.329247,38.791615 C 24.158323,38.993615 24.072861,39.317971 24.072871,39.764683 L 24.072871,42.957766 L 21.695536,42.957766 L 21.695536,39.549099 C 21.695536,39.277179 21.679993,39.092671 21.648926,38.995554 C 21.598419,38.840173 21.511017,38.715868 21.386723,38.622640 C 21.262408,38.525523 21.116742,38.476974 20.949706,38.476964 C 20.677787,38.476974 20.454426,38.579908 20.279624,38.785787 C 20.104821,38.991666 20.017420,39.329626 20.017420,39.799647 L 20.017420,42.957766 L 17.640095,42.957766 L 17.640095,36.769712 M 31.717620,38.774132 L 29.450995,38.535238 C 29.536457,38.139014 29.658813,37.828252 29.818082,37.602952 C 29.981230,37.373764 30.214307,37.175651 30.517302,37.008616 C 30.734826,36.888199 31.033943,36.794970 31.414624,36.728930 C 31.795305,36.662899 32.207063,36.629883 32.649906,36.629874 C 33.360771,36.629883 33.931797,36.670665 34.362976,36.752239 C 34.794155,36.829935 35.153476,36.995022 35.440938,37.247510 C 35.642928,37.422322 35.802188,37.670932 35.918736,37.993339 C 36.035264,38.311877 36.093529,38.616812 36.093538,38.908153 L 36.093538,41.640911 C 36.093529,41.932251 36.111011,42.161440 36.145975,42.328476 C 36.184818,42.491623 36.266392,42.701390 36.390707,42.957766 L 34.164874,42.957766 C 34.075524,42.798497 34.017250,42.678081 33.990062,42.596507 C 33.962874,42.511045 33.935676,42.378973 33.908488,42.200282 C 33.597726,42.499390 33.288903,42.713045 32.982029,42.841228 C 32.562495,43.012152 32.074991,43.097614 31.519508,43.097614 C 30.781445,43.097614 30.220134,42.926690 29.835565,42.584852 C 29.454883,42.243014 29.264538,41.821540 29.264538,41.320443 C 29.264538,40.850411 29.402437,40.463903 29.678244,40.160907 C 29.954042,39.857922 30.462916,39.632612 31.204857,39.484997 C 32.094413,39.306316 32.671267,39.182011 32.935419,39.112082 C 33.199562,39.038285 33.479248,38.943117 33.774477,38.826569 C 33.774467,38.535238 33.714264,38.331299 33.593847,38.214760 C 33.473421,38.098232 33.261715,38.039958 32.958719,38.039958 C 32.570271,38.039958 32.278931,38.102110 32.084707,38.226415 C 31.933204,38.323532 31.810838,38.506101 31.717620,38.774132 M 33.774477,40.021069 C 33.448172,40.137607 33.108273,40.240542 32.754790,40.329882 C 32.273103,40.458075 31.968169,40.584319 31.839975,40.708624 C 31.707904,40.836817 31.641863,40.982483 31.641873,41.145640 C 31.641863,41.332098 31.705965,41.485530 31.834158,41.605956 C 31.966219,41.722484 32.158504,41.780759 32.411002,41.780759 C 32.675145,41.780759 32.919876,41.716667 33.145176,41.588474 C 33.374365,41.460281 33.535573,41.304900 33.628802,41.122331 C 33.725909,40.935873 33.774467,40.695030 33.774477,40.399811 L 33.774477,40.021069 M 41.996080,36.769712 L 44.216085,36.769712 L 44.216085,42.613989 L 44.221913,42.887847 C 44.221903,43.276295 44.138390,43.645331 43.971354,43.994936 C 43.808196,44.348430 43.588724,44.633943 43.312926,44.851476 C 43.041007,45.069010 42.693341,45.226330 42.269939,45.323447 C 41.850405,45.420554 41.368718,45.469112 40.824890,45.469112 C 39.581841,45.469112 38.727240,45.282655 38.261107,44.909741 C 37.798842,44.536826 37.567715,44.037667 37.567715,43.412255 C 37.567715,43.334569 37.571603,43.229686 37.579369,43.097614 L 39.880948,43.359818 C 39.939213,43.573463 40.028563,43.721078 40.148979,43.802652 C 40.323782,43.923068 40.543255,43.983282 40.807407,43.983282 C 41.149246,43.983282 41.403683,43.891992 41.570719,43.709423 C 41.741633,43.526854 41.827095,43.208315 41.827095,42.753827 L 41.827095,41.815713 C 41.594018,42.091521 41.360952,42.291572 41.127885,42.415877 C 40.762737,42.610101 40.368452,42.707218 39.945050,42.707218 C 39.117637,42.707218 38.449503,42.345958 37.940629,41.623428 C 37.579369,41.110676 37.398739,40.432827 37.398739,39.589880 C 37.398739,38.626528 37.631806,37.892353 38.097949,37.387358 C 38.564093,36.882372 39.173962,36.629883 39.927568,36.629874 C 40.409244,36.629883 40.805468,36.711457 41.116230,36.874595 C 41.430871,37.037753 41.724151,37.307733 41.996080,37.684526 L 41.996080,36.769712 M 39.764410,39.770510 C 39.764410,40.217232 39.859578,40.549365 40.049923,40.766898 C 40.240269,40.980544 40.490818,41.087366 40.801580,41.087366 C 41.096799,41.087366 41.343470,40.976665 41.541582,40.755243 C 41.743572,40.529943 41.844577,40.191983 41.844577,39.741383 C 41.844577,39.290773 41.739694,38.946996 41.529937,38.710041 C 41.320160,38.469198 41.063784,38.348781 40.760798,38.348781 C 40.457802,38.348781 40.215020,38.459492 40.032451,38.680904 C 39.853760,38.898437 39.764410,39.261646 39.764410,39.770510 M 52.507607,40.452248 L 47.752946,40.452248 C 47.795667,40.832929 47.898612,41.116503 48.061759,41.302961 C 48.290948,41.570992 48.590055,41.705012 48.959091,41.705012 C 49.192158,41.705012 49.413580,41.646738 49.623347,41.530200 C 49.751530,41.456402 49.889429,41.326270 50.037043,41.139813 L 52.373587,41.355397 C 52.016205,41.976922 51.585026,42.423643 51.080040,42.695563 C 50.575044,42.963594 49.850586,43.097614 48.906644,43.097614 C 48.087008,43.097614 47.442184,42.983015 46.972153,42.753827 C 46.502121,42.520760 46.111734,42.153673 45.800972,41.652565 C 45.494088,41.147579 45.340656,40.555192 45.340656,39.875394 C 45.340656,38.908153 45.649469,38.125420 46.267115,37.527195 C 46.888640,36.928991 47.745170,36.629883 48.836725,36.629874 C 49.722393,36.629883 50.421612,36.763894 50.934375,37.031925 C 51.447127,37.299956 51.837514,37.688414 52.105555,38.197278 C 52.373577,38.706152 52.507597,39.368469 52.507607,40.184217 L 52.507607,40.452248 M 50.095317,39.316022 C 50.048698,38.857655 49.924393,38.529411 49.722403,38.331299 C 49.524281,38.133187 49.262077,38.034131 48.935782,38.034131 C 48.558979,38.034131 48.257932,38.183684 48.032632,38.482792 C 47.888896,38.669259 47.797616,38.946996 47.758774,39.316022 L 50.095317,39.316022' />" + " <text" + " xml:space='preserve'" + " id='text1644'" + " style='font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans'" + " y='59.288345'" + " x='12.760736'><tspan" + " id='tspan1646'" + " y='59.288345'" + " x='12.760736'>%s</tspan></text>" + "</svg>"; + + //Fill in the template + char *cErrorMessage = (char *)errorMessage.c_str(); + gchar *xmlBuffer = g_strdup_printf(xformat, cErrorMessage); + + //g_message("%s\n", xmlBuffer); + + //now show it! + showSvgFromMemory(xmlBuffer); + g_free(xmlBuffer); + showingBrokenImage = true; + +} + + + +static bool +hasSuffix(const Glib::ustring &str, Glib::ustring &ext) +{ + int strLen = str.length(); + int extLen = ext.length(); + if (extLen > strLen) + { + return false; + } + int strpos = strLen-1; + for (int extpos = extLen-1 ; extpos>=0 ; extpos--, strpos--) + { + Glib::ustring::value_type ch = str[strpos]; + if (ch != ext[extpos]) + { + if ( ((ch & 0xff80) != 0) || + static_cast<Glib::ustring::value_type>( g_ascii_tolower( static_cast<gchar>(0x07f & ch) ) ) != ext[extpos] ) + { + return false; + } + } + } + return true; +} + + +/** + * Return true if the image is loadable by Gdk, else false + */ +static bool +isValidImageIconFile(const Glib::ustring &fileName) +{ + std::vector<Gdk::PixbufFormat>formats = Gdk::Pixbuf::get_formats(); + for (unsigned int i=0; i<formats.size(); i++) + { + Gdk::PixbufFormat format = formats[i]; + std::vector<Glib::ustring>extensions = format.get_extensions(); + for (unsigned int j=0; j<extensions.size(); j++) + { + Glib::ustring ext = extensions[j]; + if (hasSuffix(fileName, ext)) + { + return true; + } + } + } + return false; +} + +bool ImageIcon::show(const Glib::ustring &fileName) +{ + + if (!Glib::file_test(fileName, Glib::FILE_TEST_EXISTS)) + return false; + + gchar *fName = (gchar *)fileName.c_str(); + //g_message("fname:%s\n", fName); + + + if (Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR)) + { + struct stat info; + if (stat(fName, &info)) + { + Glib::ustring err = "cannot get file info"; + showBrokenImage(err); + return false; + } + long fileLen = info.st_size; + if (fileLen > 0x150000L) + { + Glib::ustring err = "File too large"; + showBrokenImage(err); + return false; + } + } + + Glib::ustring svg = ".svg"; + Glib::ustring svgz = ".svgz"; + + if (hasSuffix(fileName, svg) || hasSuffix(fileName, svgz) ) + { + if (!showSvgFile(fileName)) + { + showBrokenImage(bitmapError); + return false; + } + return true; + } + else if (isValidImageIconFile(fileName)) + { + if (!showBitmap(fileName)) + { + showBrokenImage(bitmapError); + return false; + } + return true; + } + else + { + showBrokenImage("unsupported file type"); + return false; + } +} + + + + + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +/*######################################################################### +### E N D O F F I L E +#########################################################################*/ + + + diff --git a/src/ui/widget/imageicon.h b/src/ui/widget/imageicon.h new file mode 100644 index 000000000..803b2f53f --- /dev/null +++ b/src/ui/widget/imageicon.h @@ -0,0 +1,138 @@ +#ifndef __UI_DIALOG_IMAGE_H__ +#define __UI_DIALOG_IMAGE_H__ +/* + * A simple image display widget, using Inkscape's own rendering engine + * + * Authors: + * Bob Jamison + * Other dudes from The Inkscape Organization + * + * Copyright (C) 2004 The Inkscape Organization + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <glibmm/ustring.h> +#include <gtkmm/box.h> + + +class SPDocument; + +namespace Inkscape +{ +namespace UI +{ +namespace Widget +{ + + +/*######################################################################### +### ImageIcon widget +#########################################################################*/ + +/** + * This class is evolved from the SVGPreview widget of the FileChooser + * This uses Inkscape's renderer to show images in a variety of formats, + * including SVG + */ +class ImageIcon : public Gtk::VBox +{ +public: + + /** + * Constructor + */ + ImageIcon(); + + /** + * Construct from a file name + */ + ImageIcon(const Glib::ustring &fileName); + + /** + * Copy Constructor + */ + ImageIcon(const ImageIcon &other); + + /** + * Destructor + */ + ~ImageIcon(); + + /** + * + */ + bool showSvgDocument(const SPDocument *doc); + + /** + * + */ + bool showSvgFile(const Glib::ustring &fileName); + + /** + * + */ + bool showSvgFromMemory(const char *xmlBuffer); + + /** + * Show image embedded in SVG + */ + bool showBitmap(const Glib::ustring &fileName); + + /** + * Show the "Too large" image + */ + void showBrokenImage(const Glib::ustring &reason); + + /** + * + */ + bool show(const Glib::ustring &fileName); + +private: + + /** + * basic initialization, called by the various constructors + */ + void init(); + + /** + * The svg document we are currently showing + */ + SPDocument *document; + + /** + * The sp_svg_view widget + */ + Gtk::Widget *viewerGtkmm; + + /** + * are we currently showing the "broken image" image? + */ + bool showingBrokenImage; + + + /** + * will be set by showImageIcon as a side-effect of an error + */ + Glib::ustring bitmapError; + + + /** + * will be set by showImageIcon as a side-effect of an error + */ + Glib::ustring svgError; + +}; + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif /* __UI_DIALOG_IMAGE_H__ */ +/*######################################################################### +### E N D O F F I L E +#########################################################################*/ diff --git a/src/ui/widget/labelled.cpp b/src/ui/widget/labelled.cpp new file mode 100644 index 000000000..64f9aef83 --- /dev/null +++ b/src/ui/widget/labelled.cpp @@ -0,0 +1,102 @@ +/** + * \brief Labelled Widget - Adds a label with optional icon or suffix to + * another widget. + * + * Authors: + * Carl Hetherington <inkscape@carlh.net> + * Derek P. Moore <derekm@hackunix.org> + * + * Copyright (C) 2004 Carl Hetherington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* For getting the Gtkmmified Icon manager */ +#include "widgets/icon.h" + +#include "labelled.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Construct a Labelled Widget. + * + * \param label Label. + * \param widget Widget to label; should be allocated with new, as it will + * be passed to Gtk::manage(). + * \param suffix Suffix, placed after the widget (defaults to ""). + * \param icon Icon filename, placed before the label (defaults to ""). + * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the text + * indicates the next character should be used for the + * mnemonic accelerator key (defaults to true). + */ +Labelled::Labelled(Glib::ustring const &label, Glib::ustring const &tooltip, + Gtk::Widget *widget, + Glib::ustring const &suffix, + Glib::ustring const &icon, + bool mnemonic) + : _widget(widget), + _label(new Gtk::Label(label, 1.0, 0.5, mnemonic)), + _suffix(new Gtk::Label(suffix, 0.0, 0.5)), + _tooltips() +{ + g_assert(g_utf8_validate(icon.c_str(), -1, NULL)); + if (icon != "") { + _icon = sp_icon_get_icon(icon.c_str(), GTK_ICON_SIZE_LARGE_TOOLBAR); + pack_start(*Gtk::manage(_icon), Gtk::PACK_SHRINK); + } + pack_start(*Gtk::manage(_label), Gtk::PACK_EXPAND_WIDGET, 6); + pack_start(*Gtk::manage(_widget), Gtk::PACK_SHRINK, 6); + if (mnemonic) { + _label->set_mnemonic_widget(*_widget); + } + _tooltips.set_tip(*_widget, tooltip); +} + + +/** + * Allow the setting of the width of the labelled widget + */ +void Labelled::setWidgetSizeRequest(int width, int height) +{ + if (_widget) + _widget->set_size_request(width, height); + + +} + +const Gtk::Widget* const +Labelled::getWidget() const +{ + return _widget; +} + +const Gtk::Label* const +Labelled::getLabel() const +{ + return _label; +} + + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/labelled.h b/src/ui/widget/labelled.h new file mode 100644 index 000000000..1823aeef2 --- /dev/null +++ b/src/ui/widget/labelled.h @@ -0,0 +1,65 @@ +/** + * \brief Labelled Widget - Adds a label with optional icon or suffix to + * another widget. + * + * Authors: + * Carl Hetherington <inkscape@carlh.net> + * Derek P. Moore <derekm@hackunix.org> + * + * Copyright (C) 2004 Carl Hetherington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_LABELLED_H +#define INKSCAPE_UI_WIDGET_LABELLED_H + +#include <gtkmm/box.h> +#include <gtkmm/label.h> +#include <gtkmm/image.h> +#include <gtkmm/tooltips.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Labelled : public Gtk::HBox +{ +public: + Labelled(Glib::ustring const &label, Glib::ustring const &tooltip, + Gtk::Widget *widget, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + bool mnemonic = true); + + /** + * Allow the setting of the width of the labelled widget + */ + void setWidgetSizeRequest(int width, int height); + const Gtk::Widget* const getWidget() const; + const Gtk::Label* const getLabel() const; + +protected: + Gtk::Widget *_widget; + Gtk::Label *_label; + Gtk::Label *_suffix; + Gtk::Widget *_icon; + Gtk::Tooltips _tooltips; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_LABELLED_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/licensor.cpp b/src/ui/widget/licensor.cpp new file mode 100644 index 000000000..9a5713220 --- /dev/null +++ b/src/ui/widget/licensor.cpp @@ -0,0 +1,146 @@ +/** \file + * + * Authors: + * bulia byak <buliabyak@users.sf.net> + * Bryce W. Harrington <bryce@bryceharrington.org> + * Lauris Kaplinski <lauris@kaplinski.com> + * Jon Phillips <jon@rejon.org> + * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm) + * + * Copyright (C) 2000 - 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtkmm/entry.h> + +#include "ui/widget/entity-entry.h" +#include "ui/widget/registry.h" +#include "dialogs/rdf.h" +#include "inkscape.h" + +#include "licensor.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +//=================================================== + +const struct rdf_license_t _proprietary_license = + {_("Proprietary"), "", 0}; + +class LicenseItem : public Gtk::RadioButton { +public: + LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr); +protected: + void on_toggled(); + struct rdf_license_t const *_lic; + EntityEntry *_eep; + Registry &_wr; +}; + +LicenseItem::LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr) +: Gtk::RadioButton(license->name), _lic(license), _eep(entity), _wr(wr) +{ + static Gtk::RadioButtonGroup group = get_group(); + static bool first = true; + if (first) first = false; + else set_group (group); +} + +/// \pre it is assumed that the license URI entry is a Gtk::Entry +void +LicenseItem::on_toggled() +{ + if (_wr.isUpdating()) return; + + _wr.setUpdating (true); + rdf_set_license (SP_ACTIVE_DOCUMENT, _lic->details ? _lic : 0); + sp_document_done (SP_ACTIVE_DOCUMENT); + _wr.setUpdating (false); + reinterpret_cast<Gtk::Entry*>(_eep->_packable)->set_text (_lic->uri); + _eep->on_changed(); +} + +//--------------------------------------------------- + +Licensor::Licensor() +: Gtk::VBox(false,4) +{ +} + +Licensor::~Licensor() +{ + if (_eentry) delete _eentry; +} + +void +Licensor::init (Gtk::Tooltips& tt, Registry& wr) +{ + /* add license-specific metadata entry areas */ + rdf_work_entity_t* entity = rdf_find_entity ( "license_uri" ); + _eentry = EntityEntry::create (entity, tt, wr); + + LicenseItem *i; + wr.setUpdating (true); + i = manage (new LicenseItem (&_proprietary_license, _eentry, wr)); + add (*i); + LicenseItem *pd = i; + for (struct rdf_license_t * license = rdf_licenses; + license && license->name; + license++) { + i = manage (new LicenseItem (license, _eentry, wr)); + add(*i); + } + pd->set_active(); + wr.setUpdating (false); + + Gtk::HBox *box = manage (new Gtk::HBox); + pack_start (*box, true, true, 0); + + box->pack_start (_eentry->_label, false, false, 5); + box->pack_start (*_eentry->_packable, true, true, 0); + + show_all_children(); +} + +void +Licensor::update (SPDocument *doc) +{ + /* identify the license info */ + struct rdf_license_t * license = rdf_get_license (doc); + + if (license) { + int i; + for (i=0; rdf_licenses[i].name; i++) + if (license == &rdf_licenses[i]) + break; + reinterpret_cast<LicenseItem*>(children()[i+1].get_widget())->set_active(); + } + else { + reinterpret_cast<LicenseItem*>(children()[0].get_widget())->set_active(); + } + + /* update the URI */ + _eentry->update (doc); +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/licensor.h b/src/ui/widget/licensor.h new file mode 100644 index 000000000..9f41a6d0d --- /dev/null +++ b/src/ui/widget/licensor.h @@ -0,0 +1,59 @@ +/** \file + * \brief Widget for specifying a document's license; part of document + * preferences dialog. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_LICENSOR__H +#define INKSCAPE_UI_WIDGET_LICENSOR__H + +#include <gtkmm/box.h> + +class SPDocument; + +namespace Gtk { + class Tooltips; +} + +namespace Inkscape { + namespace UI { + namespace Widget { + +class EntityEntry; +class Registry; + + +class Licensor : public Gtk::VBox { +public: + Licensor(); + virtual ~Licensor(); + void init (Gtk::Tooltips&, Registry&); + void update (SPDocument *doc); + +protected: + EntityEntry *_eentry; +}; + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_LICENSOR__H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/makefile.in b/src/ui/widget/makefile.in new file mode 100644 index 000000000..2dfa00344 --- /dev/null +++ b/src/ui/widget/makefile.in @@ -0,0 +1,17 @@ +# Convenience stub makefile to call the real Makefile. + +@SET_MAKE@ + +# Explicit so that it's the default rule. +all: + cd ../.. && $(MAKE) ui/widget/all + +clean %.a %.o: + cd ../.. && $(MAKE) ui/widget/$@ + +.PHONY: all clean + +OBJEXT = @OBJEXT@ + +.SUFFIXES: +.SUFFIXES: .a .$(OBJEXT) diff --git a/src/ui/widget/notebook-page.cpp b/src/ui/widget/notebook-page.cpp new file mode 100644 index 000000000..83be16a43 --- /dev/null +++ b/src/ui/widget/notebook-page.cpp @@ -0,0 +1,49 @@ +/** + * \brief Notebook page widget + * + * Author: + * Bryce Harrington <bryce@bryceharrington.org> + * + * Copyright (C) 2004 Bryce Harrington + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "notebook-page.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Construct a NotebookPage + * + * \param label Label. + */ + +NotebookPage::NotebookPage(int n_rows, int n_columns) + :_table(n_rows, n_columns) +{ + set_border_width(2); + _table.set_spacings(2); + pack_start(_table, false, false, 0); +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/notebook-page.h b/src/ui/widget/notebook-page.h new file mode 100644 index 000000000..0341cb659 --- /dev/null +++ b/src/ui/widget/notebook-page.h @@ -0,0 +1,50 @@ +/** + * \brief Notebook Page Widget - A tabbed notebook page for dialogs. + * + * Author: + * Bryce Harrington <bryce@bryceharrington.org> + * + * Copyright (C) 2004 Bryce Harrington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H +#define INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H + +#include <gtkmm/box.h> +#include <gtkmm/frame.h> +#include <gtkmm/table.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +class NotebookPage : public Gtk::VBox +{ +public: + NotebookPage(); + NotebookPage(int n_rows, int n_columns); + + Gtk::Table& table() { return _table; } + +protected: + Gtk::Table _table; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_NOTEBOOK_PAGE_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp new file mode 100644 index 000000000..ea0efeb2d --- /dev/null +++ b/src/ui/widget/page-sizer.cpp @@ -0,0 +1,357 @@ +/** \file + * + * Paper-size widget and helper functions + * + * Authors: + * bulia byak <buliabyak@users.sf.net> + * Lauris Kaplinski <lauris@kaplinski.com> + * Jon Phillips <jon@rejon.org> + * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm) + * + * Copyright (C) 2000 - 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <cmath> +#include <gtkmm/optionmenu.h> +#include <gtkmm/frame.h> +#include <gtkmm/table.h> + +#include "ui/widget/scalar-unit.h" + +#include "helper/units.h" +#include "inkscape.h" +#include "desktop-handles.h" +#include "document.h" +#include "page-sizer.h" + +using std::pair; + +namespace Inkscape { +namespace UI { +namespace Widget { + +struct PaperSize { + char const * const name; + double const smaller; + double const larger; + SPUnitId const unit; +}; + + /** \note + * The ISO page sizes in the table below differ from ghostscript's idea of page sizes (by + * less than 1pt). Being off by <1pt should be OK for most purposes, but may cause fuzziness + * (antialiasing) problems when printing to 72dpi or 144dpi printers or bitmap files due to + * postscript's different coordinate system (y=0 meaning bottom of page in postscript and top + * of page in SVG). I haven't looked into whether this does in fact cause fuzziness, I merely + * note the possibility. Rounding done by extension/internal/ps.cpp (e.g. floor/ceil calls) + * will also affect whether fuzziness occurs. + * + * The remainder of this comment discusses the origin of the numbers used for ISO page sizes in + * this table and in ghostscript. + * + * The versions here, in mm, are the official sizes according to + * <a href="http://en.wikipedia.org/wiki/Paper_sizes">http://en.wikipedia.org/wiki/Paper_sizes</a> + * at 2005-01-25. (The ISO entries in the below table + * were produced mechanically from the table on that page.) + * + * (The rule seems to be that A0, B0, ..., D0. sizes are rounded to the nearest number of mm + * from the "theoretical size" (i.e. 1000 * sqrt(2) or pow(2.0, .25) or the like), whereas + * going from e.g. A0 to A1 always take the floor of halving -- which by chance coincides + * exactly with flooring the "theoretical size" for n != 0 instead of the rounding to nearest + * done for n==0.) + * + * Ghostscript paper sizes are given in gs_statd.ps according to gs(1). gs_statd.ps always + * uses an integer number of pt: sometimes gs_statd.ps rounds to nearest (e.g. a1), sometimes + * floors (e.g. a10), sometimes ceils (e.g. a8). + * + * I'm not sure how ghostscript's gs_statd.ps was calculated: it isn't just rounding the + * "theoretical size" of each page to pt (see a0), nor is it rounding the a0 size times an + * appropriate power of two (see a1). Possibly it was prepared manually, with a human applying + * inconsistent rounding rules when converting from mm to pt. + */ + /** \todo + * Should we include the JIS B series (used in Japan) + * (JIS B0 is sometimes called JB0, and similarly for JB1 etc)? + * Should we exclude B7--B10 and A7--10 to make the list smaller ? + * Should we include any of the ISO C, D and E series (see below) ? + */ + +static PaperSize const inkscape_papers[] = { + { "A4", 210, 297, SP_UNIT_MM }, + { "US Letter", 8.5, 11, SP_UNIT_IN }, + { "US Legal", 8.5, 14, SP_UNIT_IN }, + { "US Executive", 7.25, 10.5, SP_UNIT_IN }, + { "A0", 841, 1189, SP_UNIT_MM }, + { "A1", 594, 841, SP_UNIT_MM }, + { "A2", 420, 594, SP_UNIT_MM }, + { "A3", 297, 420, SP_UNIT_MM }, + { "A5", 148, 210, SP_UNIT_MM }, + { "A6", 105, 148, SP_UNIT_MM }, + { "A7", 74, 105, SP_UNIT_MM }, + { "A8", 52, 74, SP_UNIT_MM }, + { "A9", 37, 52, SP_UNIT_MM }, + { "A10", 26, 37, SP_UNIT_MM }, + { "B0", 1000, 1414, SP_UNIT_MM }, + { "B1", 707, 1000, SP_UNIT_MM }, + { "B2", 500, 707, SP_UNIT_MM }, + { "B3", 353, 500, SP_UNIT_MM }, + { "B4", 250, 353, SP_UNIT_MM }, + { "B5", 176, 250, SP_UNIT_MM }, + { "B6", 125, 176, SP_UNIT_MM }, + { "B7", 88, 125, SP_UNIT_MM }, + { "B8", 62, 88, SP_UNIT_MM }, + { "B9", 44, 62, SP_UNIT_MM }, + { "B10", 31, 44, SP_UNIT_MM }, + +#if 0 /* Whether to include or exclude these depends on how big we mind our page size menu + becoming. C series is used for envelopes; don't know what D and E series are used for. */ + { "C0", 917, 1297, SP_UNIT_MM }, + { "C1", 648, 917, SP_UNIT_MM }, + { "C2", 458, 648, SP_UNIT_MM }, + { "C3", 324, 458, SP_UNIT_MM }, + { "C4", 229, 324, SP_UNIT_MM }, + { "C5", 162, 229, SP_UNIT_MM }, + { "C6", 114, 162, SP_UNIT_MM }, + { "C7", 81, 114, SP_UNIT_MM }, + { "C8", 57, 81, SP_UNIT_MM }, + { "C9", 40, 57, SP_UNIT_MM }, + { "C10", 28, 40, SP_UNIT_MM }, + { "D1", 545, 771, SP_UNIT_MM }, + { "D2", 385, 545, SP_UNIT_MM }, + { "D3", 272, 385, SP_UNIT_MM }, + { "D4", 192, 272, SP_UNIT_MM }, + { "D5", 136, 192, SP_UNIT_MM }, + { "D6", 96, 136, SP_UNIT_MM }, + { "D7", 68, 96, SP_UNIT_MM }, + { "E3", 400, 560, SP_UNIT_MM }, + { "E4", 280, 400, SP_UNIT_MM }, + { "E5", 200, 280, SP_UNIT_MM }, + { "E6", 140, 200, SP_UNIT_MM }, +#endif + + { "CSE", 462, 649, SP_UNIT_PT }, + { "US #10 Envelope", 4.125, 9.5, SP_UNIT_IN }, // TODO: Select landscape by default. + /* See http://www.hbp.com/content/PCR_envelopes.cfm for a much larger list of US envelope + sizes. */ + { "DL Envelope", 110, 220, SP_UNIT_MM }, // TODO: Select landscape by default. + { "Ledger/Tabloid", 11, 17, SP_UNIT_IN }, + /* Note that `Folio' (used in QPrinter/KPrinter) is deliberately absent from this list, as it + means different sizes to different people: different people may expect the width to be + either 8, 8.25 or 8.5 inches, and the height to be either 13 or 13.5 inches, even + restricting our interpretation to foolscap folio. If you wish to introduce a folio-like + page size to the list, then please consider using a name more specific than just `Folio' or + `Foolscap Folio'. */ + { "Banner 468x60", 60, 468, SP_UNIT_PX }, // TODO: Select landscape by default. + { "Icon 16x16", 16, 16, SP_UNIT_PX }, + { "Icon 32x32", 32, 32, SP_UNIT_PX }, + { NULL, 0, 0, SP_UNIT_PX }, +}; + +//=================================================== +static const SPUnit _px_unit = sp_unit_get_by_id (SP_UNIT_PX); + +class SizeMenuItem : public Gtk::MenuItem { +public: + SizeMenuItem (PaperSize const * paper, PageSizer * widget) + : Gtk::MenuItem (paper ? paper->name : _("Custom")), + _paper(paper), _parent(widget) {} +protected: + PaperSize const * _paper; + PageSizer *_parent; + void on_activate(); +}; + +void +SizeMenuItem::on_activate() +{ + if (_parent == 0) // handle Custom entry + return; + + double w = _paper->smaller, h = _paper->larger; + SPUnit const &src_unit = sp_unit_get_by_id (_paper->unit); + sp_convert_distance (&w, &src_unit, &_px_unit); + sp_convert_distance (&h, &src_unit, &_px_unit); + if (_parent->_landscape) + _parent->setDim (h, w, true); + else + _parent->setDim (w, h, true); +} + +//--------------------------------------------------- + +PageSizer::PageSizer() +: Gtk::VBox(false,4) +{ + Gtk::HBox *hbox_size = manage (new Gtk::HBox (false, 4)); + pack_start (*hbox_size, false, false, 0); + Gtk::Label *label_size = manage (new Gtk::Label (_("Page size:"), 1.0, 0.5)); + hbox_size->pack_start (*label_size, false, false, 0); + _omenu_size = manage (new Gtk::OptionMenu); + hbox_size->pack_start (*_omenu_size, true, true, 0); + Gtk::Menu *menu_size = manage (new Gtk::Menu); + + for (PaperSize const *paper = inkscape_papers; paper->name; paper++) { + SizeMenuItem *item = manage (new SizeMenuItem (paper, this)); + menu_size->append (*item); + } + SizeMenuItem *item = manage (new SizeMenuItem (0, 0)); + menu_size->prepend (*item); + _omenu_size->set_menu (*menu_size); +} + +PageSizer::~PageSizer() +{ + _portrait_connection.disconnect(); + _landscape_connection.disconnect(); + _changedw_connection.disconnect(); + _changedh_connection.disconnect(); +} + +void +PageSizer::init (Registry& reg) +{ + Gtk::HBox *hbox_ori = manage (new Gtk::HBox); + pack_start (*hbox_ori, false, false, 0); + Gtk::Label *label_ori = manage (new Gtk::Label (_("Page orientation:"), 0.0, 0.5)); + hbox_ori->pack_start (*label_ori, false, false, 0); + _rb_land = manage (new Gtk::RadioButton (_("Landscape"))); + Gtk::RadioButton::Group group = _rb_land->get_group(); + hbox_ori->pack_end (*_rb_land, false, false, 5); + _rb_port = manage (new Gtk::RadioButton (_("Portrait"))); + hbox_ori->pack_end (*_rb_port, false, false, 5); + _rb_port->set_group (group); + _rb_port->set_active (true); + + /* Custom paper frame */ + Gtk::Frame *frame = manage (new Gtk::Frame(_("Custom size"))); + pack_start (*frame, false, false, 0); + Gtk::Table *table = manage (new Gtk::Table (4, 2, false)); + table->set_border_width (4); + table->set_row_spacings (4); + table->set_col_spacings (4); + frame->add (*table); + + _wr = ® + + _rum.init (_("Units:"), "units", *_wr); + _rusw.init (_("Width:"), _("Width of paper"), "width", _rum, *_wr); + _rush.init (_("Height:"), _("Height of paper"), "height", _rum, *_wr); + + table->attach (*_rum._label, 0,1,0,1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); + table->attach (*_rum._sel, 1,2,0,1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); + table->attach (*_rusw.getSU(), 0,2,1,2, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); + table->attach (*_rush.getSU(), 0,2,2,3, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); + + _landscape_connection = _rb_land->signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_landscape)); + _portrait_connection = _rb_port->signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_portrait)); + _changedw_connection = _rusw.getSU()->signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed)); + _changedh_connection = _rush.getSU()->signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed)); + + show_all_children(); +} + +/** + * \param w, h given in px + */ +void +PageSizer::setDim (double w, double h, bool update) +{ + _landscape = w>h; + _rb_land->set_active (_landscape ? true : false); + _rb_port->set_active (_landscape ? false : true); + _omenu_size->set_history (1 + find_paper_size (w, h)); + + Unit const& unit = _rum._sel->getUnit(); + if (!update) _changedw_connection.block(); + _rusw.setValue (w / unit.factor); + if (!update) _changedw_connection.unblock(); + if (!update) _changedh_connection.block(); + _rush.setValue (h / unit.factor); + if (!update) _changedh_connection.unblock(); +} + +void +PageSizer::setDoc (double w, double h) +{ + setDim (w, h); + if (!SP_ACTIVE_DESKTOP || _wr->isUpdating()) + return; + + SPDocument *doc = SP_DT_DOCUMENT(SP_ACTIVE_DESKTOP); + sp_document_set_width (doc, _rusw.getSU()->getValue("px"), &_px_unit); + sp_document_set_height (doc, _rush.getSU()->getValue("px"), &_px_unit); + sp_document_done (doc); +} + +/** + * Returns an index into inkscape_papers of a paper of the specified + * size (specified in px), or -1 if there's no such paper. + */ +int +PageSizer::find_paper_size (double w, double h) const +{ + double given[2]; + if ( w < h ) { + given[0] = w; given[1] = h; + } else { + given[0] = h; given[1] = w; + } + g_return_val_if_fail(given[0] <= given[1], -1); + for (unsigned i = 0; i < G_N_ELEMENTS(inkscape_papers) - 1; ++i) { + SPUnit const &i_unit = sp_unit_get_by_id(inkscape_papers[i].unit); + double const i_sizes[2] = { sp_units_get_pixels(inkscape_papers[i].smaller, i_unit), + sp_units_get_pixels(inkscape_papers[i].larger, i_unit) }; + g_return_val_if_fail(i_sizes[0] <= i_sizes[1], -1); + if ((std::abs(given[0] - i_sizes[0]) <= .1) && + (std::abs(given[1] - i_sizes[1]) <= .1) ) + { + return (int) i; + } + } + return -1; +} + +void +PageSizer::on_portrait() +{ + double w = _rusw.getSU()->getValue ("px"); + double h = _rush.getSU()->getValue ("px"); + if (h<w) setDoc (h, w); +} + +void +PageSizer::on_landscape() +{ + double w = _rusw.getSU()->getValue ("px"); + double h = _rush.getSU()->getValue ("px"); + if (w<h) setDoc (h, w); +} + +void +PageSizer::on_value_changed() +{ + if (_wr->isUpdating()) return; + + setDoc (_rusw.getSU()->getValue("px"), _rush.getSU()->getValue("px")); +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h new file mode 100644 index 000000000..e17628c76 --- /dev/null +++ b/src/ui/widget/page-sizer.h @@ -0,0 +1,67 @@ +/** \file + * \brief Widget for specifying page size; part of Document Preferences dialog. + * + * Author: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_PAGE_SIZER__H +#define INKSCAPE_UI_WIDGET_PAGE_SIZER__H + +#include <sigc++/sigc++.h> +#include <gtkmm/box.h> +#include "ui/widget/registry.h" +#include "ui/widget/registered-widget.h" + +namespace Gtk { + class OptionMenu; + class RadioButton; +} + +namespace Inkscape { + namespace UI { + namespace Widget { + +/// Widget containing all widgets for specifying page size. +class PageSizer : public Gtk::VBox { +public: + PageSizer(); + virtual ~PageSizer(); + void init (Registry& reg); + void setDim (double w, double h, bool update = false); + bool _landscape; + +protected: + void setDoc (double w, double h); + int find_paper_size (double w, double h) const; + void on_portrait(); + void on_landscape(); + void on_value_changed(); + + RegisteredUnitMenu _rum; + RegisteredScalarUnit _rusw, _rush; + Gtk::OptionMenu *_omenu_size; + Gtk::RadioButton *_rb_port, *_rb_land; + sigc::connection _portrait_connection, _landscape_connection; + sigc::connection _changedw_connection, _changedh_connection; + Registry *_wr; +}; + +}}} + +#endif /* INKSCAPE_UI_WIDGET_PAGE_SIZER__H */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp new file mode 100644 index 000000000..67aca690a --- /dev/null +++ b/src/ui/widget/panel.cpp @@ -0,0 +1,248 @@ +/** + * \brief Panel widget + * + * Authors: + * Bryce Harrington <bryce@bryceharrington.org> + * Jon A. Cruz <jon@joncruz.org> + * + * Copyright (C) 2004 Bryce Harrington + * Copyright (C) 2005 Jon A. Cruz + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <glibmm/i18n.h> + +#include "panel.h" +#include "../../prefs-utils.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Construct a Panel + * + * \param label Label. + */ + +Panel::Panel(const gchar *prefs_path) : + _prefs_path(NULL), + _fillable(0) +{ + _prefs_path = prefs_path; + init(); +} + +Panel::Panel() : + _prefs_path(NULL), + _fillable(0) +{ + init(); +} + +Panel::Panel(Glib::ustring const &label) : + _prefs_path(NULL), + _fillable(0) +{ + this->label = label; + init(); +} + +Panel::~Panel() +{ +} + +void Panel::init() +{ + Glib::ustring tmp("<"); + tabTitle.set_label(this->label); + + guint panel_size = 0; + if (_prefs_path) { + panel_size = prefs_get_int_attribute_limited (_prefs_path, "panel_size", 1, 0, 10); + } + + guint panel_mode = 0; + if (_prefs_path) { + panel_mode = prefs_get_int_attribute_limited (_prefs_path, "panel_mode", 1, 0, 10); + } + + tabButton.set_menu(menu); + Gtk::MenuItem* dummy = manage(new Gtk::MenuItem(tmp)); + menu.append( *dummy ); + menu.append( *manage(new Gtk::SeparatorMenuItem()) ); + { + const char *things[] = { + N_("small"), + N_("medium"), + N_("large"), + N_("huge") + }; + Gtk::RadioMenuItem::Group groupOne; + for ( unsigned int i = 0; i < G_N_ELEMENTS(things); i++ ) { + Glib::ustring foo(gettext(things[i])); + Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, foo)); + menu.append(*single); + if ( i == panel_size ) { + single->set_active(true); + } + single->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 0, i) ); + } + } + menu.append( *manage(new Gtk::SeparatorMenuItem()) ); + Gtk::RadioMenuItem::Group group; + Glib::ustring oneLab(_("List")); + Glib::ustring twoLab(_("Grid")); + Gtk::RadioMenuItem *one = manage(new Gtk::RadioMenuItem(group, oneLab)); + Gtk::RadioMenuItem *two = manage(new Gtk::RadioMenuItem(group, twoLab)); + + if (panel_mode == 0) { + one->set_active(true); + } else if (panel_mode == 1) { + two->set_active(true); + } + + menu.append( *one ); + menu.append( *two ); + menu.append( *manage(new Gtk::SeparatorMenuItem()) ); + one->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 1, 0) ); + two->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), 1, 1) ); + + closeButton.set_label("X"); + + topBar.pack_start(tabTitle); + + topBar.pack_end(closeButton, false, false); + topBar.pack_end(tabButton, false, false); + + pack_start( topBar, false, false ); + + show_all_children(); + + bounceCall (0, panel_size); + bounceCall (1, panel_mode); +} + +void Panel::setLabel(Glib::ustring const &label) +{ + this->label = label; + tabTitle.set_label(this->label); +} + +void Panel::_regItem( Gtk::MenuItem* item, int group, int id ) +{ + menu.append( *item ); + item->signal_activate().connect( sigc::bind<int, int>( sigc::mem_fun(*this, &Panel::bounceCall), group + 2, id) ); +} + +void Panel::restorePanelPrefs() +{ + guint panel_size = 0; + if (_prefs_path) { + panel_size = prefs_get_int_attribute_limited (_prefs_path, "panel_size", 1, 0, 10); + } + guint panel_mode = 0; + if (_prefs_path) { + panel_mode = prefs_get_int_attribute_limited (_prefs_path, "panel_mode", 1, 0, 10); + } + bounceCall (0, panel_size); + bounceCall (1, panel_mode); +} + +void Panel::bounceCall(int i, int j) +{ + menu.set_active(0); + switch ( i ) { + case 0: + if (_prefs_path) prefs_set_int_attribute (_prefs_path, "panel_size", j); + if ( _fillable ) { + ViewType currType = _fillable->getPreviewType(); + switch ( j ) { + case 0: + { + _fillable->setStyle(Gtk::ICON_SIZE_MENU, currType); + } + break; + case 1: + { + _fillable->setStyle(Gtk::ICON_SIZE_SMALL_TOOLBAR, currType); + } + break; + case 2: + { + _fillable->setStyle(Gtk::ICON_SIZE_BUTTON, currType); + } + break; + case 3: + { + _fillable->setStyle(Gtk::ICON_SIZE_DIALOG, currType); + } + break; + default: + ; + } + } + break; + case 1: + if (_prefs_path) prefs_set_int_attribute (_prefs_path, "panel_mode", j); + if ( _fillable ) { + Gtk::BuiltinIconSize currSize = _fillable->getPreviewSize(); + switch ( j ) { + case 0: + { + _fillable->setStyle(currSize, VIEW_TYPE_LIST); + } + break; + case 1: + { + _fillable->setStyle(currSize, VIEW_TYPE_GRID); + } + break; + default: + break; + } + } + break; + default: + _handleAction( i - 2, j ); + } +} + + + + + +Glib::ustring const &Panel::getLabel() const +{ + return label; +} + +void Panel::_setTargetFillable( PreviewFillable *target ) +{ + _fillable = target; +} + +void Panel::_handleAction( int setId, int itemId ) +{ +// for subclasses to override +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/panel.h b/src/ui/widget/panel.h new file mode 100644 index 000000000..07225b8ce --- /dev/null +++ b/src/ui/widget/panel.h @@ -0,0 +1,80 @@ +/** + * \brief Generic Panel widget - A generic dockable container. + * + * Authors: + * Bryce Harrington <bryce@bryceharrington.org> + * Jon A. Cruz <jon@joncruz.org> + * + * Copyright (C) 2004 Bryce Harrington + * Copyright (C) 2005 Jon A. Cruz + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_UI_WIDGET_PANEL_H +#define SEEN_INKSCAPE_UI_WIDGET_PANEL_H + +#include <gtkmm/box.h> +#include <gtkmm/frame.h> +#include <gtkmm/table.h> +#include <gtkmm/button.h> +#include <gtkmm/label.h> +#include <gtkmm/menu.h> +#include <gtkmm/optionmenu.h> +#include "../previewfillable.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Panel : public Gtk::VBox +{ +public: + Panel(); + virtual ~Panel(); + Panel(Glib::ustring const &label); + Panel(const gchar *prefs_path); + + void setLabel(Glib::ustring const &label); + Glib::ustring const &getLabel() const; + + const gchar *_prefs_path; + void restorePanelPrefs(); + +protected: + void _setTargetFillable( PreviewFillable *target ); + void _regItem( Gtk::MenuItem* item, int group, int id ); + + virtual void _handleAction( int setId, int itemId ); + + +private: + void init(); + void bounceCall(int i, int j); + + Glib::ustring label; + + Gtk::HBox topBar; + Gtk::Label tabTitle; + Gtk::OptionMenu tabButton; + Gtk::Menu menu; + Gtk::Button closeButton; + PreviewFillable *_fillable; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // SEEN_INKSCAPE_UI_WIDGET_PANEL_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp new file mode 100644 index 000000000..cc389c611 --- /dev/null +++ b/src/ui/widget/preferences-widget.cpp @@ -0,0 +1,278 @@ +/** + * \brief Inkscape Preferences dialog + * + * Authors: + * Marco Scholten + * + * Copyright (C) 2004, 2006 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtkmm/frame.h> +#include <gtkmm/alignment.h> +#include <gtkmm/box.h> + +#include "prefs-utils.h" +#include "ui/widget/preferences-widget.h" +#include "verbs.h" +#include "selcue.h" +#include <iostream> +#include "enums.h" +#include "inkscape.h" +#include "desktop-handles.h" +#include "message-stack.h" +#include "style.h" +#include "selection.h" +#include "selection-chemistry.h" +#include "xml/repr.h" + +using namespace Inkscape::UI::Widget; + +namespace Inkscape { +namespace UI { +namespace Widget { + +DialogPage::DialogPage() +{ + this->set_border_width(12); + this->set_col_spacings(12); + this->set_row_spacings(6); +} + +void DialogPage::add_line(bool indent, const Glib::ustring label, Gtk::Widget& widget, const Glib::ustring suffix, const Glib::ustring& tip, bool expand_widget) +{ + int start_col; + int row = this->property_n_rows(); + Gtk::Widget* w; + if (expand_widget) + { + w = &widget; + } + else + { + Gtk::HBox* hb = Gtk::manage(new Gtk::HBox()); + hb->set_spacing(12); + hb->pack_start(widget,false,false); + w = (Gtk::Widget*) hb; + } + if (label != "") + { + Gtk::Label* label_widget; + label_widget = Gtk::manage(new Gtk::Label(label , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true)); + label_widget->set_mnemonic_widget(widget); + if (indent) + { + Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment()); + alignment->set_padding(0, 0, 12, 0); + alignment->add(*label_widget); + this->attach(*alignment , 0, 1, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0); + } + else + this->attach(*label_widget , 0, 1, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0); + start_col = 1; + } + else + start_col = 0; + + if (start_col == 0 && indent) //indent this widget + { + Gtk::Alignment* alignment = Gtk::manage(new Gtk::Alignment()); + alignment->set_padding(0, 0, 12, 0); + alignment->add(*w); + this->attach(*alignment, start_col, 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::AttachOptions(), 0, 0); + } + else + { + this->attach(*w, start_col, 2, row, row + 1, Gtk::FILL | Gtk::EXPAND, Gtk::AttachOptions(), 0, 0); + } + + if (suffix != "") + { + Gtk::Label* suffix_widget = Gtk::manage(new Gtk::Label(suffix , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true)); + if (expand_widget) + this->attach(*suffix_widget, 2, 3, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0); + else + ((Gtk::HBox*)w)->pack_start(*suffix_widget,false,false); + } + + if (tip != "") + { + _tooltips.set_tip (widget, tip); + } + +} + +void DialogPage::add_group_header(Glib::ustring name) +{ + int row = this->property_n_rows(); + if (name != "") + { + Gtk::Label* label_widget = Gtk::manage(new Gtk::Label(Glib::ustring(/*"<span size='large'>*/"<b>") + name + + Glib::ustring("</b>"/*</span>"*/) , Gtk::ALIGN_LEFT , Gtk::ALIGN_CENTER, true)); + label_widget->set_use_markup(true); + this->attach(*label_widget , 0, 4, row, row + 1, Gtk::FILL, Gtk::AttachOptions(), 0, 0); + if (row != 1) + this->set_row_spacing(row - 1, 18); + } +} + +void PrefCheckButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr, + bool default_value) +{ + _prefs_path = prefs_path; + _attr = attr; + this->set_label(label); + this->set_active( prefs_get_int_attribute (_prefs_path.c_str(), _attr.c_str(), (int)default_value) ); +} + +void PrefCheckButton::on_toggled() +{ + if (this->is_visible()) //only take action if the user toggled it + { + prefs_set_int_attribute (_prefs_path.c_str(), _attr.c_str(), (int) this->get_active()); + } +} + +void PrefRadioButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr, + const std::string& string_value, bool default_value, PrefRadioButton* group_member) +{ + _value_type = VAL_STRING; + _prefs_path = prefs_path; + _attr = attr; + _string_value = string_value; + this->set_label(label); + if (group_member) + { + Gtk::RadioButtonGroup rbg = group_member->get_group(); + this->set_group(rbg); + } + const gchar* val = prefs_get_string_attribute( _prefs_path.c_str(), _attr.c_str() ); + if ( val ) + this->set_active( std::string( val ) == _string_value); + else + this->set_active( false ); +} + +void PrefRadioButton::init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr, + int int_value, bool default_value, PrefRadioButton* group_member) +{ + _value_type = VAL_INT; + _prefs_path = prefs_path; + _attr = attr; + _int_value = int_value; + this->set_label(label); + if (group_member) + { + Gtk::RadioButtonGroup rbg = group_member->get_group(); + this->set_group(rbg); + } + if (default_value) + this->set_active( prefs_get_int_attribute( _prefs_path.c_str(), _attr.c_str(), int_value ) == _int_value); + else + this->set_active( prefs_get_int_attribute( _prefs_path.c_str(), _attr.c_str(), int_value + 1 )== _int_value); +} + +void PrefRadioButton::on_toggled() +{ + this->changed_signal.emit(this->get_active()); + if (this->is_visible() && this->get_active() ) //only take action if toggled by user (to active) + { + if ( _value_type == VAL_STRING ) + prefs_set_string_attribute ( _prefs_path.c_str(), _attr.c_str(), _string_value.c_str()); + else if ( _value_type == VAL_INT ) + prefs_set_int_attribute ( _prefs_path.c_str(), _attr.c_str(), _int_value); + } +} + +void PrefSpinButton::init(const std::string& prefs_path, const std::string& attr, + double lower, double upper, double step_increment, double page_increment, + double default_value, bool is_int, bool is_percent) +{ + _prefs_path = prefs_path; + _attr = attr; + _is_int = is_int; + _is_percent = is_percent; + + double value; + if (is_int) + if (is_percent) + value = 100 * prefs_get_double_attribute_limited (prefs_path.c_str(), attr.c_str(), default_value, lower/100.0, upper/100.0); + else + value = (double) prefs_get_int_attribute_limited (prefs_path.c_str(), attr.c_str(), (int) default_value, (int) lower, (int) upper); + else + value = prefs_get_double_attribute_limited (prefs_path.c_str(), attr.c_str(), default_value, lower, upper); + + this->set_range (lower, upper); + this->set_increments (step_increment, page_increment); + this->set_numeric(); + this->set_value (value); + this->set_width_chars(6); + if (is_int) + this->set_digits(0); + else if (step_increment < 0.1) + this->set_digits(3); + else + this->set_digits(2); + +} + +void PrefSpinButton::on_value_changed() +{ + if (this->is_visible()) //only take action if user changed value + { + if (_is_int) + if (_is_percent) + prefs_set_double_attribute(_prefs_path.c_str(), _attr.c_str(), this->get_value()/100.0); + else + prefs_set_int_attribute(_prefs_path.c_str(), _attr.c_str(), (int) this->get_value()); + else + prefs_set_double_attribute (_prefs_path.c_str(), _attr.c_str(), this->get_value()); + } +} + +void PrefCombo::init(const std::string& prefs_path, const std::string& attr, + Glib::ustring labels[], int values[], int num_items, int default_value) +{ + _prefs_path = prefs_path; + _attr = attr; + int row = 0; + int value = prefs_get_int_attribute (_prefs_path.c_str(), _attr.c_str(), default_value); + + for (int i = 0 ; i < num_items; ++i) + { + this->append_text(labels[i]); + _values.push_back(values[i]); + if (value == values[i]) + row = i; + } + this->set_active(row); +} + +void PrefCombo::on_changed() +{ + if (this->is_visible()) //only take action if user changed value + { + prefs_set_int_attribute (_prefs_path.c_str(), _attr.c_str(), _values[this->get_active_row_number()]); + std::cout << "combo set: " << _prefs_path << " " << _attr << " " << _values[this->get_active_row_number()] << std::endl; + } +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h new file mode 100644 index 000000000..a5a594114 --- /dev/null +++ b/src/ui/widget/preferences-widget.h @@ -0,0 +1,117 @@ +/** + * \brief Inkscape Preferences dialog + * + * Authors: + * Marco Scholten + * + * Copyright (C) 2004, 2006 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H +#define INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H + +#include <iostream> +#include <vector> +#include <gtkmm/table.h> +#include <gtkmm/comboboxtext.h> +#include <gtkmm/spinbutton.h> +#include <gtkmm/tooltips.h> +#include <gtkmm/treeview.h> +#include <gtkmm/radiobutton.h> +#include <gtkmm/frame.h> +#include <sigc++/sigc++.h> +//#include <glibmm/i18n.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +class PrefCheckButton : public Gtk::CheckButton +{ +public: + void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr, + bool default_value); +protected: + std::string _prefs_path; + std::string _attr; + bool _int_value; + void on_toggled(); +}; + +class PrefRadioButton : public Gtk::RadioButton +{ +public: + void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr, + int int_value, bool default_value, PrefRadioButton* group_member); + void init(const Glib::ustring& label, const std::string& prefs_path, const std::string& attr, + const std::string& string_value, bool default_value, PrefRadioButton* group_member); + sigc::signal<void, bool> changed_signal; +protected: + std::string _prefs_path; + std::string _attr; + std::string _string_value; + int _value_type; + enum + { + VAL_INT, + VAL_STRING + }; + int _int_value; + void on_toggled(); +}; + +class PrefSpinButton : public Gtk::SpinButton +{ +public: + void init(const std::string& prefs_path, const std::string& attr, + double lower, double upper, double step_increment, double page_increment, + double default_value, bool is_int, bool is_percent); +protected: + std::string _prefs_path; + std::string _attr; + bool _is_int; + bool _is_percent; + void on_value_changed(); +}; + +class PrefCombo : public Gtk::ComboBoxText +{ +public: + void init(const std::string& prefs_path, const std::string& attr, + Glib::ustring labels[], int values[], int num_items, int default_value); +protected: + std::string _prefs_path; + std::string _attr; + std::vector<int> _values; + void on_changed(); +}; + +class DialogPage : public Gtk::Table +{ +public: + DialogPage(); + void add_line(bool indent, const Glib::ustring label, Gtk::Widget& widget, const Glib::ustring suffix, const Glib::ustring& tip, bool expand = true); + void add_group_header(Glib::ustring name); +protected: + Gtk::Tooltips _tooltips; +}; + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif //INKSCAPE_UI_WIDGET_INKSCAPE_PREFERENCES_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp new file mode 100644 index 000000000..918742e75 --- /dev/null +++ b/src/ui/widget/registered-widget.cpp @@ -0,0 +1,409 @@ +/** \file + * + * + * Authors: + * bulia byak <buliabyak@users.sf.net> + * Bryce W. Harrington <bryce@bryceharrington.org> + * Lauris Kaplinski <lauris@kaplinski.com> + * Jon Phillips <jon@rejon.org> + * Ralf Stephan <ralf@ark.in-berlin.de> (Gtkmm) + * + * Copyright (C) 2000 - 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "ui/widget/color-picker.h" +#include "ui/widget/registry.h" +#include "ui/widget/scalar-unit.h" + +#include "helper/units.h" +#include "xml/repr.h" +#include "svg/svg.h" +#include "svg/stringstream.h" + +#include "inkscape.h" +#include "document.h" +#include "desktop-handles.h" +#include "sp-namedview.h" + +#include "registered-widget.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +//=================================================== + +//--------------------------------------------------- + + + +//==================================================== + +RegisteredCheckButton::RegisteredCheckButton() +: _button(0) +{ +} + +RegisteredCheckButton::~RegisteredCheckButton() +{ + _toggled_connection.disconnect(); + if (_button) delete _button; +} + +void +RegisteredCheckButton::init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right) +{ + _button = new Gtk::CheckButton; + _tt.set_tip (*_button, tip); + _button->add (*manage (new Gtk::Label (label))); + _button->set_alignment (right? 1.0 : 0.0, 0.5); + _key = key; + _wr = ≀ + _toggled_connection = _button->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredCheckButton::on_toggled)); +} + +void +RegisteredCheckButton::setActive (bool b) +{ + _button->set_active (b); +} + +void +RegisteredCheckButton::on_toggled() +{ + if (_wr->isUpdating()) + return; + + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (!dt) { + return; + } + + SPDocument *doc = SP_DT_DOCUMENT(dt); + + Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt)); + _wr->setUpdating (true); + + gboolean saved = sp_document_get_undo_sensitive (doc); + sp_document_set_undo_sensitive (doc, FALSE); + sp_repr_set_boolean(repr, _key.c_str(), _button->get_active()); + doc->rroot->setAttribute("sodipodi:modified", "true"); + sp_document_set_undo_sensitive (doc, saved); + sp_document_done (doc); + + _wr->setUpdating (false); +} + +RegisteredUnitMenu::RegisteredUnitMenu() +: _label(0), _sel(0) +{ +} + +RegisteredUnitMenu::~RegisteredUnitMenu() +{ + _changed_connection.disconnect(); + if (_label) delete _label; + if (_sel) delete _sel; +} + +void +RegisteredUnitMenu::init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr) +{ + _label = new Gtk::Label (label, 1.0, 0.5); + _sel = new UnitMenu (); + _sel->setUnitType (UNIT_TYPE_LINEAR); + _wr = ≀ + _key = key; + _changed_connection = _sel->signal_changed().connect (sigc::mem_fun (*this, &RegisteredUnitMenu::on_changed)); +} + +void +RegisteredUnitMenu::setUnit (const SPUnit* unit) +{ + _sel->setUnit (sp_unit_get_abbreviation (unit)); +} + +void +RegisteredUnitMenu::on_changed() +{ + if (_wr->isUpdating()) + return; + + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (!dt) + return; + + Inkscape::SVGOStringStream os; + os << _sel->getUnitAbbr(); + + _wr->setUpdating (true); + + SPDocument *doc = SP_DT_DOCUMENT(dt); + gboolean saved = sp_document_get_undo_sensitive (doc); + sp_document_set_undo_sensitive (doc, FALSE); + Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt)); + repr->setAttribute(_key.c_str(), os.str().c_str()); + doc->rroot->setAttribute("sodipodi:modified", "true"); + sp_document_set_undo_sensitive (doc, saved); + sp_document_done (doc); + + _wr->setUpdating (false); +} + + +RegisteredScalarUnit::RegisteredScalarUnit() +: _widget(0), _um(0) +{ +} + +RegisteredScalarUnit::~RegisteredScalarUnit() +{ + if (_widget) delete _widget; + _value_changed_connection.disconnect(); +} + +void +RegisteredScalarUnit::init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, const RegisteredUnitMenu &rum, Registry& wr) +{ + _widget = new ScalarUnit (label, tip, UNIT_TYPE_LINEAR, "", "", rum._sel); + _widget->initScalar (-1e6, 1e6); + _widget->setUnit (rum._sel->getUnitAbbr()); + _widget->setDigits (2); + _key = key; + _um = rum._sel; + _value_changed_connection = _widget->signal_value_changed().connect (sigc::mem_fun (*this, &RegisteredScalarUnit::on_value_changed)); + _wr = ≀ +} + +ScalarUnit* +RegisteredScalarUnit::getSU() +{ + return _widget; +} + +void +RegisteredScalarUnit::setValue (double val) +{ + _widget->setValue (val); + on_value_changed(); +} + +void +RegisteredScalarUnit::on_value_changed() +{ + if (_wr->isUpdating()) + return; + + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (!dt) + return; + + Inkscape::SVGOStringStream os; + os << _widget->getValue(""); + if (_um) + os << _um->getUnitAbbr(); + + _wr->setUpdating (true); + + SPDocument *doc = SP_DT_DOCUMENT(dt); + gboolean saved = sp_document_get_undo_sensitive (doc); + sp_document_set_undo_sensitive (doc, FALSE); + Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt)); + repr->setAttribute(_key.c_str(), os.str().c_str()); + doc->rroot->setAttribute("sodipodi:modified", "true"); + sp_document_set_undo_sensitive (doc, saved); + sp_document_done (doc); + + _wr->setUpdating (false); +} + +RegisteredColorPicker::RegisteredColorPicker() +: _label(0), _cp(0) +{ +} + +RegisteredColorPicker::~RegisteredColorPicker() +{ + _changed_connection.disconnect(); + if (_cp) delete _cp; + if (_label) delete _label; +} + +void +RegisteredColorPicker::init (const Glib::ustring& label, const Glib::ustring& title, const Glib::ustring& tip, const Glib::ustring& ckey, const Glib::ustring& akey, Registry& wr) +{ + _label = new Gtk::Label (label, 1.0, 0.5); + _cp = new ColorPicker (title,tip,0,true); + _ckey = ckey; + _akey = akey; + _wr = ≀ + _changed_connection = _cp->connectChanged (sigc::mem_fun (*this, &RegisteredColorPicker::on_changed)); +} + +void +RegisteredColorPicker::setRgba32 (guint32 rgba) +{ + _cp->setRgba32 (rgba); +} + +void +RegisteredColorPicker::closeWindow() +{ + _cp->closeWindow(); +} + +void +RegisteredColorPicker::on_changed (guint32 rgba) +{ + if (_wr->isUpdating() || !SP_ACTIVE_DESKTOP) + return; + + _wr->setUpdating (true); + Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(SP_ACTIVE_DESKTOP)); + gchar c[32]; + sp_svg_write_color(c, 32, rgba); + repr->setAttribute(_ckey.c_str(), c); + sp_repr_set_css_double(repr, _akey.c_str(), (rgba & 0xff) / 255.0); + _wr->setUpdating (false); +} + +RegisteredSuffixedInteger::RegisteredSuffixedInteger() +: _label(0), _sb(0), + _adj(0.0,0.0,100.0,1.0,1.0,1.0), + _suffix(0) +{ +} + +RegisteredSuffixedInteger::~RegisteredSuffixedInteger() +{ + _changed_connection.disconnect(); + if (_label) delete _label; + if (_suffix) delete _suffix; + if (_sb) delete _sb; +} + +void +RegisteredSuffixedInteger::init (const Glib::ustring& label, const Glib::ustring& suffix, const Glib::ustring& key, Registry& wr) +{ + _key = key; + _label = new Gtk::Label (label); + _label->set_alignment (1.0, 0.5); + _sb = new Gtk::SpinButton (_adj, 1.0, 0); + _suffix = new Gtk::Label (suffix); + _hbox.pack_start (*_sb, true, true, 0); + _hbox.pack_start (*_suffix, false, false, 0); + + _changed_connection = _adj.signal_value_changed().connect (sigc::mem_fun(*this, &RegisteredSuffixedInteger::on_value_changed)); + _wr = ≀ +} + +void +RegisteredSuffixedInteger::setValue (int i) +{ + _adj.set_value (i); +} + +void +RegisteredSuffixedInteger::on_value_changed() +{ + if (_wr->isUpdating() || !SP_ACTIVE_DESKTOP) + return; + + _wr->setUpdating (true); + + SPDesktop* dt = SP_ACTIVE_DESKTOP; + Inkscape::XML::Node *repr = SP_OBJECT_REPR(SP_DT_NAMEDVIEW(dt)); + Inkscape::SVGOStringStream os; + int value = int(_adj.get_value()); + os << value; + + repr->setAttribute(_key.c_str(), os.str().c_str()); + sp_document_done(SP_DT_DOCUMENT(dt)); + + _wr->setUpdating (false); +} + +RegisteredRadioButtonPair::RegisteredRadioButtonPair() +: _hbox(0) +{ +} + +RegisteredRadioButtonPair::~RegisteredRadioButtonPair() +{ + _changed_connection.disconnect(); +} + +void +RegisteredRadioButtonPair::init (const Glib::ustring& label, +const Glib::ustring& label1, const Glib::ustring& label2, +const Glib::ustring& tip1, const Glib::ustring& tip2, +const Glib::ustring& key, Registry& wr) +{ + _hbox = new Gtk::HBox; + _hbox->add (*manage (new Gtk::Label (label))); + _rb1 = manage (new Gtk::RadioButton (label1)); + _hbox->add (*_rb1); + Gtk::RadioButtonGroup group = _rb1->get_group(); + _rb2 = manage (new Gtk::RadioButton (group, label2, false)); + _hbox->add (*_rb2); + _rb2->set_active(); + _tt.set_tip (*_rb1, tip1); + _tt.set_tip (*_rb2, tip2); + _key = key; + _wr = ≀ + _changed_connection = _rb1->signal_toggled().connect (sigc::mem_fun (*this, &RegisteredRadioButtonPair::on_value_changed)); +} + +void +RegisteredRadioButtonPair::setValue (bool second) +{ + if (second) _rb2->set_active(); + else _rb1->set_active(); +} + +void +RegisteredRadioButtonPair::on_value_changed() +{ + if (_wr->isUpdating()) + return; + + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (!dt) + return; + + _wr->setUpdating (true); + + bool second = _rb2->get_active(); + SPDocument *doc = SP_DT_DOCUMENT(dt); + gboolean saved = sp_document_get_undo_sensitive (doc); + sp_document_set_undo_sensitive (doc, FALSE); + Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt)); + repr->setAttribute(_key.c_str(), second ? "true" : "false"); + doc->rroot->setAttribute("sodipodi:modified", "true"); + sp_document_set_undo_sensitive (doc, saved); + sp_document_done (doc); + + _wr->setUpdating (false); +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h new file mode 100644 index 000000000..7138f4640 --- /dev/null +++ b/src/ui/widget/registered-widget.h @@ -0,0 +1,175 @@ +/** \file + * \brief + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_ +#define INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_ + +#include <gtkmm/box.h> +#include <gtkmm/adjustment.h> + +class SPUnit; + +namespace Gtk { + class HScale; + class RadioButton; + class SpinButton; + class ToggleButton; +} + +namespace Inkscape { +namespace UI { +namespace Widget { + +class ColorPicker; +class Registry; +class ScalarUnit; +class UnitMenu; + +class RegisteredCheckButton { +public: + RegisteredCheckButton(); + ~RegisteredCheckButton(); + void init (const Glib::ustring& label, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr, bool right=true); + void setActive (bool); + + Gtk::ToggleButton *_button; + +protected: + Gtk::Tooltips _tt; + sigc::connection _toggled_connection; + Registry *_wr; + Glib::ustring _key; + void on_toggled(); +}; + +class RegisteredUnitMenu { +public: + RegisteredUnitMenu(); + ~RegisteredUnitMenu(); + void init (const Glib::ustring& label, const Glib::ustring& key, Registry& wr); + void setUnit (const SPUnit*); + Gtk::Label *_label; + UnitMenu *_sel; + sigc::connection _changed_connection; + +protected: + void on_changed(); + Registry *_wr; + Glib::ustring _key; +}; + +class RegisteredScalarUnit { +public: + RegisteredScalarUnit(); + ~RegisteredScalarUnit(); + void init (const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + const RegisteredUnitMenu &rum, + Registry& wr); + ScalarUnit* getSU(); + void setValue (double); + +protected: + ScalarUnit *_widget; + sigc::connection _value_changed_connection; + UnitMenu *_um; + Registry *_wr; + Glib::ustring _key; + void on_value_changed(); +}; + +class RegisteredColorPicker { +public: + RegisteredColorPicker(); + ~RegisteredColorPicker(); + void init (const Glib::ustring& label, + const Glib::ustring& title, + const Glib::ustring& tip, + const Glib::ustring& ckey, + const Glib::ustring& akey, + Registry& wr); + void setRgba32 (guint32); + void closeWindow(); + + Gtk::Label *_label; + ColorPicker *_cp; + +protected: + Glib::ustring _ckey, _akey; + Registry *_wr; + void on_changed (guint32); + sigc::connection _changed_connection; +}; + +class RegisteredSuffixedInteger { +public: + RegisteredSuffixedInteger(); + ~RegisteredSuffixedInteger(); + void init (const Glib::ustring& label1, + const Glib::ustring& label2, + const Glib::ustring& key, + Registry& wr); + void setValue (int); + Gtk::Label *_label; + Gtk::HBox _hbox; + +protected: + Gtk::SpinButton *_sb; + Gtk::Adjustment _adj; + Gtk::Label *_suffix; + Glib::ustring _key; + Registry *_wr; + sigc::connection _changed_connection; + void on_value_changed(); +}; + +class RegisteredRadioButtonPair { +public: + RegisteredRadioButtonPair(); + ~RegisteredRadioButtonPair(); + void init (const Glib::ustring& label, + const Glib::ustring& label1, + const Glib::ustring& label2, + const Glib::ustring& tip1, + const Glib::ustring& tip2, + const Glib::ustring& key, + Registry& wr); + void setValue (bool second); + Gtk::HBox *_hbox; + +protected: + Gtk::RadioButton *_rb1, *_rb2; + Gtk::Tooltips _tt; + Glib::ustring _key; + Registry *_wr; + sigc::connection _changed_connection; + void on_value_changed(); +}; + + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_REGISTERED_WIDGET__H_ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/registry.cpp b/src/ui/widget/registry.cpp new file mode 100644 index 000000000..aa92e6ecb --- /dev/null +++ b/src/ui/widget/registry.cpp @@ -0,0 +1,58 @@ +/** \file + * + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "registry.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +//=================================================== + +//--------------------------------------------------- + +Registry::Registry() : _updating(false) {} + +Registry::~Registry() {} + +bool +Registry::isUpdating() +{ + return _updating; +} + +void +Registry::setUpdating (bool upd) +{ + _updating = upd; +} + +//==================================================== + + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/registry.h b/src/ui/widget/registry.h new file mode 100644 index 000000000..4d7ad3068 --- /dev/null +++ b/src/ui/widget/registry.h @@ -0,0 +1,54 @@ +/** \file + * \brief + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_REGISTRY__H +#define INKSCAPE_UI_WIDGET_REGISTRY__H + +#include <map> +#include <glibmm/i18n.h> +#include <glibmm/ustring.h> + +namespace Gtk { + class Object; +} + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Registry { +public: + Registry(); + ~Registry(); + + bool isUpdating(); + void setUpdating (bool); + +protected: + bool _updating; +}; + +} // namespace Dialog +} // namespace UI +} // namespace Widget + +#endif // INKSCAPE_UI_WIDGET_REGISTRY__H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/ruler.cpp b/src/ui/widget/ruler.cpp new file mode 100644 index 000000000..f2a59338d --- /dev/null +++ b/src/ui/widget/ruler.cpp @@ -0,0 +1,197 @@ +/** \file + * Gtkmm facade/wrapper around SPRuler code that formerly lived + * in desktop-events.cpp + */ +/* + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * Lauris Kaplinski + * + * Copyright (C) 2005 Ralf Stephan + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#if defined(WIN32) || defined(__APPLE__) +# include <glibmm/i18n.h> +#endif + +#include <gtkmm/ruler.h> +#include "helper/units.h" +#include "widgets/ruler.h" +#include "ui/widget/ruler.h" + +#include "xml/repr.h" +#include "display/guideline.h" +#include "desktop.h" +#include "desktop-handles.h" +#include "document.h" +#include "sp-namedview.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +void +Ruler::init(SPDesktop *dt, Gtk::Widget &w) +{ + _dt = dt; + _canvas_widget = &w; + _dragging = false; + _guide = 0; + sp_ruler_set_metric(GTK_RULER(_r->gobj()), SP_PT); + _r->set_range(-500, 500, 0, 1000); +} + +void +Ruler::get_range(double &lo, double &up, double &pos, double &max) +{ + _r->get_range(lo, up, pos, max); +} + +void +Ruler::set_range(double lo, double up, double pos, double max) +{ + _r->set_range(lo, up, pos, max); +} + +/// Set metric from namedview +void +Ruler::update_metric() +{ + if (!_dt) return; + sp_ruler_set_metric(GTK_RULER(_r->gobj()), _dt->namedview->getDefaultMetric()); +} + +/// Returns text to be used for tooltip for ruler. +/// \todo incorrect +Glib::ustring +Ruler::get_tip() +{ + return gettext(sp_unit_get_plural( _dt + ? _dt->namedview->doc_units + : &sp_unit_get_by_id(SP_UNIT_PT) )); +} + +/// Helper that gets mouse coordinates relative to canvas widget. +void +Ruler::canvas_get_pointer(int &x, int &y) +{ + Gdk::ModifierType mask; + (void) _canvas_widget->get_window()->get_pointer(x, y, mask); +} + +NR::Point +Ruler::get_event_dt() +{ + int wx, wy; + canvas_get_pointer(wx, wy); + NR::Point const event_win(wx, wy); + NR::Point const event_w(sp_canvas_window_to_world(_dt->canvas, event_win)); + return _dt->w2d(event_w); +} + +bool +Ruler::on_button_press_event(GdkEventButton *evb) +{ + g_assert(_dt); + NR::Point const &event_dt = get_event_dt(); + Inkscape::XML::Node *repr = SP_OBJECT_REPR(_dt->namedview); + + if (evb->button == 1) { + _dragging = true; + sp_repr_set_boolean(repr, "showguides", TRUE); + sp_repr_set_boolean(repr, "inkscape:guide-bbox", TRUE); + double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ]; + _guide = sp_guideline_new(_dt->guides, guide_pos_dt, !_horiz_f); + sp_guideline_set_color(SP_GUIDELINE(_guide), _dt->namedview->guidehicolor); + (void) get_window()->pointer_grab(false, + Gdk::BUTTON_RELEASE_MASK | + Gdk::POINTER_MOTION_MASK | + Gdk::POINTER_MOTION_HINT_MASK, + evb->time); + } + return false; +} + +bool +Ruler::on_motion_notify_event(GdkEventMotion *) +{ + g_assert(_dt); + NR::Point const &event_dt = get_event_dt(); + + if (_dragging) { + double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ]; + sp_guideline_set_position(SP_GUIDELINE(_guide), guide_pos_dt); + _dt->set_coordinate_status(event_dt); + _dt->setPosition(event_dt); + } + return false; +} + +bool +Ruler::on_button_release_event(GdkEventButton *evb) +{ + g_assert(_dt); + int wx, wy; + canvas_get_pointer(wx, wy); + NR::Point const &event_dt = get_event_dt(); + + if (_dragging && evb->button == 1) { + Gdk::Window::pointer_ungrab(evb->time); + gtk_object_destroy(GTK_OBJECT(_guide)); + _guide = 0; + _dragging = false; + + if ( (_horiz_f ? wy : wx ) >= 0 ) { + Inkscape::XML::Node *repr = sp_repr_new("sodipodi:guide"); + repr->setAttribute("orientation", _horiz_f ? "horizontal" : "vertical"); + double const guide_pos_dt = event_dt[ _horiz_f ? NR::Y : NR::X ]; + sp_repr_set_svg_double(repr, "position", guide_pos_dt); + SP_OBJECT_REPR(_dt->namedview)->appendChild(repr); + Inkscape::GC::release(repr); + sp_document_done(SP_DT_DOCUMENT(_dt)); + } + _dt->set_coordinate_status(event_dt); + } + return false; +} + +//------------------------------------------------------------ +HRuler::HRuler() +{ + _dt = 0; + _r = static_cast<Gtk::HRuler*>(Glib::wrap(static_cast<GtkWidget*> (sp_hruler_new()))); + add(*_r); + _horiz_f = true; +} + +HRuler::~HRuler() +{ +} + + +VRuler::VRuler() +{ + _dt = 0; + _r = static_cast<Gtk::VRuler*>(Glib::wrap(static_cast<GtkWidget*> (sp_vruler_new()))); + add(*_r); + _horiz_f = false; +} + +VRuler::~VRuler() +{ +} + +}}} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/ruler.h b/src/ui/widget/ruler.h new file mode 100644 index 000000000..74dbf028c --- /dev/null +++ b/src/ui/widget/ruler.h @@ -0,0 +1,88 @@ +#ifndef __UI_WIDGET_RULER_H__ +#define __UI_WIDGET_RULER_H__ + +/** \file + * Gtkmm facade/wrapper around sp_rulers. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 The Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/eventbox.h> +#include "libnr/nr-point.h" + +struct SPCanvasItem; +struct SPDesktop; +namespace Glib { + class ustring; +} +namespace Gtk { + class Ruler; +} +namespace Inkscape { + namespace UI { + namespace Widget { + +class Ruler : public Gtk::EventBox +{ +public: + void init (SPDesktop*, Gtk::Widget&); + void get_range (double&, double&, double&, double&); + void set_range (double, double, double, double); + void update_metric(); + Glib::ustring get_tip(); + +protected: + SPDesktop *_dt; + SPCanvasItem *_guide; + Gtk::Widget *_canvas_widget; + Gtk::Ruler *_r; + bool _horiz_f, _dragging; + + virtual bool on_button_press_event (GdkEventButton *); + virtual bool on_motion_notify_event (GdkEventMotion *); + virtual bool on_button_release_event (GdkEventButton *); + +private: + void canvas_get_pointer (int&, int&); + NR::Point get_event_dt(); +}; + +/// Horizontal ruler +class HRuler : public Ruler +{ +public: + HRuler(); + ~HRuler(); +}; + +/// Vertical ruler +class VRuler : public Ruler +{ +public: + VRuler(); + ~VRuler(); +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/scalar-unit.cpp b/src/ui/widget/scalar-unit.cpp new file mode 100644 index 000000000..8727ed052 --- /dev/null +++ b/src/ui/widget/scalar-unit.cpp @@ -0,0 +1,252 @@ +/** + * \brief Scalar Unit Widget - A labelled text box, with spin buttons and + * optional icon or suffix, for entering the values of various unit + * types. + * + * A ScalarUnit is a control for entering, viewing, or manipulating + * numbers with units. This differs from ordinary numbers like 2 or + * 3.14 because the number portion of a scalar *only* has meaning + * when considered with its unit type. For instance, 12 m and 12 in + * have very different actual values, but 1 m and 100 cm have the same + * value. The ScalarUnit allows us to abstract the presentation of + * the scalar to the user from the internal representations used by + * the program. + * + * Authors: + * Bryce Harrington <bryce@bryceharrington.org> + * Derek P. Moore <derekm@hackunix.org> + * buliabyak@gmail.com + * + * Copyright (C) 2004-2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "scalar-unit.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Construct a ScalarUnit + * + * \param label Label. + * \param unit_type Unit type (defaults to UNIT_TYPE_LINEAR). + * \param suffix Suffix, placed after the widget (defaults to ""). + * \param icon Icon filename, placed before the label (defaults to ""). + * \param unit_menu UnitMenu drop down; if not specified, one will be created + * and displayed after the widget (defaults to NULL). + * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label + * indicates the next character should be used for the + * mnemonic accelerator key (defaults to true). + */ +ScalarUnit::ScalarUnit(Glib::ustring const &label, Glib::ustring const &tooltip, + UnitType unit_type, + Glib::ustring const &suffix, + Glib::ustring const &icon, + UnitMenu *unit_menu, + bool mnemonic) + : Scalar(label, tooltip, suffix, icon, mnemonic), + _unit_menu(unit_menu), + _hundred_percent(0), + _absolute_is_increment(false), + _percentage_is_increment(false) +{ + if (_unit_menu == NULL) { + _unit_menu = new UnitMenu(); + g_assert(_unit_menu); + _unit_menu->setUnitType(unit_type); + pack_start(*Gtk::manage(_unit_menu), false, false, 4); + } + _unit_menu->signal_changed() + .connect_notify(sigc::mem_fun(*this, &ScalarUnit::on_unit_changed)); +} + +/** + * Initializes the scalar based on the settings in _unit_menu. + * Requires that _unit_menu has already been initialized. + */ +void +ScalarUnit::initScalar(double min_value, double max_value) +{ + g_assert(_unit_menu != NULL); + Scalar::setDigits(_unit_menu->getDefaultDigits()); + Scalar::setIncrements(_unit_menu->getDefaultStep(), + _unit_menu->getDefaultPage()); + Scalar::setRange(min_value, max_value); +} + +/** Sets the unit for the ScalarUnit widget */ +bool +ScalarUnit::setUnit(Glib::ustring const &unit) { + g_assert(_unit_menu != NULL); + // First set the unit + if (!_unit_menu->setUnit(unit)) { + return false; + } + lastUnits = unit; + return true; +} + +/** Gets the object for the currently selected unit */ +Unit +ScalarUnit::getUnit() const { + g_assert(_unit_menu != NULL); + return _unit_menu->getUnit(); +} + +/** Gets the UnitType ID for the unit */ +UnitType +ScalarUnit::getUnitType() const { + g_assert(_unit_menu); + return _unit_menu->getUnitType(); +} + +/** Sets the number and unit system */ +void +ScalarUnit::setValue(double number, Glib::ustring const &units) { + g_assert(_unit_menu != NULL); + _unit_menu->setUnit(units); + Scalar::setValue(number); +} + +/** Sets the number only */ +void +ScalarUnit::setValue(double number) { + Scalar::setValue(number); +} + +/** Returns the value in the given unit system */ +double +ScalarUnit::getValue(Glib::ustring const &unit_name) const { + g_assert(_unit_menu != NULL); + if (unit_name == "") { + // Return the value in the default units + return Scalar::getValue(); + } else { + double conversion = _unit_menu->getConversion(unit_name); + return conversion * Scalar::getValue(); + } +} + +void +ScalarUnit::setHundredPercent(double number) +{ + _hundred_percent = number; +} + +void +ScalarUnit::setAbsoluteIsIncrement(bool value) +{ + _absolute_is_increment = value; +} + +void +ScalarUnit::setPercentageIsIncrement(bool value) +{ + _percentage_is_increment = value; +} + +/** Convert value from % to absolute, using _hundred_percent and *_is_increment flags */ +double +ScalarUnit::PercentageToAbsolute(double value) +{ + // convert from percent to absolute + double convertedVal = 0; + double hundred_converted = _hundred_percent / _unit_menu->getConversion("px"); // _hundred_percent is in px + if (_percentage_is_increment) + value += 100; + convertedVal = 0.01 * hundred_converted * value; + if (_absolute_is_increment) + convertedVal -= hundred_converted; + + return convertedVal; +} + +/** Convert value from absolute to %, using _hundred_percent and *_is_increment flags */ +double +ScalarUnit::AbsoluteToPercentage(double value) +{ + double convertedVal = 0; + // convert from absolute to percent + if (_hundred_percent == 0) { + if (_percentage_is_increment) + convertedVal = 0; + else + convertedVal = 100; + } else { + double hundred_converted = _hundred_percent / _unit_menu->getConversion("px", lastUnits); // _hundred_percent is in px + if (_absolute_is_increment) + value += hundred_converted; + convertedVal = 100 * value / hundred_converted; + if (_percentage_is_increment) + convertedVal -= 100; + } + + return convertedVal; +} + +/** Assuming the current unit is absolute, get the corresponding % value */ +double +ScalarUnit::getAsPercentage() +{ + double convertedVal = AbsoluteToPercentage(Scalar::getValue()); + return convertedVal; +} + + +/** Assuming the current unit is absolute, set the value corresponding to a given % */ +void +ScalarUnit::setFromPercentage(double value) +{ + double absolute = PercentageToAbsolute(value); + Scalar::setValue(absolute); +} + + +/** Signal handler for updating the value and suffix label when unit is changed */ +void +ScalarUnit::on_unit_changed() +{ + g_assert(_unit_menu != NULL); + + Glib::ustring abbr = _unit_menu->getUnitAbbr(); + _suffix->set_label(abbr); + + Inkscape::Util::UnitTable &table = _unit_menu->getUnitTable(); + Inkscape::Util::Unit new_unit = (table.getUnit(abbr)); + Inkscape::Util::Unit old_unit = (table.getUnit(lastUnits)); + + double convertedVal = 0; + if (old_unit.type == UNIT_TYPE_DIMENSIONLESS && new_unit.type == UNIT_TYPE_LINEAR) { + convertedVal = PercentageToAbsolute(Scalar::getValue()); + } else if (old_unit.type == UNIT_TYPE_LINEAR && new_unit.type == UNIT_TYPE_DIMENSIONLESS) { + convertedVal = AbsoluteToPercentage(Scalar::getValue()); + } else { + double conversion = _unit_menu->getConversion(lastUnits); + convertedVal = Scalar::getValue() / conversion; + } + Scalar::setValue(convertedVal); + + lastUnits = abbr; +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/scalar-unit.h b/src/ui/widget/scalar-unit.h new file mode 100644 index 000000000..c99161dad --- /dev/null +++ b/src/ui/widget/scalar-unit.h @@ -0,0 +1,85 @@ +/** + * \brief Scalar Unit Widget - A labelled text box, with spin buttons and + * optional icon or suffix, for entering the values of various unit + * types. + * + * Authors: + * Bryce Harrington <bryce@bryceharrington.org> + * Derek P. Moore <derekm@hackunix.org> + * buliabyak@gmail.com + * + * Copyright (C) 2004-2005 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_SCALAR_UNIT_H +#define INKSCAPE_UI_WIDGET_SCALAR_UNIT_H + +#include "scalar.h" +#include "unit-menu.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class ScalarUnit : public Scalar +{ +public: + ScalarUnit(Glib::ustring const &label, Glib::ustring const &tooltip, + UnitType unit_type = UNIT_TYPE_LINEAR, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + UnitMenu *unit_menu = NULL, + bool mnemonic = true); + + void initScalar(double min_value, double max_value); + + Unit getUnit() const; + UnitType getUnitType() const; + double getValue(Glib::ustring const &units) const; + + bool setUnit(Glib::ustring const &units); + void setValue(double number, Glib::ustring const &units); + void setValue(double number); + + void setHundredPercent(double number); + void setAbsoluteIsIncrement(bool value); + void setPercentageIsIncrement(bool value); + + double PercentageToAbsolute(double value); + double AbsoluteToPercentage(double value); + + double getAsPercentage(); + void setFromPercentage(double value); + + void on_unit_changed(); + +protected: + UnitMenu *_unit_menu; + + double _hundred_percent; // the length that corresponds to 100%, in px, for %-to/from-absolute conversions + + bool _absolute_is_increment; // if true, 120% with _hundred_percent=100px gets converted to/from 20px; otherwise, to/from 120px + bool _percentage_is_increment; // if true, 120px with _hundred_percent=100px gets converted to/from 20%; otherwise, to/from 120% + // if both are true, 20px is converted to/from 20% if _hundred_percent=100px + + Glib::ustring lastUnits; // previously selected unit, for conversions +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_SCALAR_UNIT_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/scalar.cpp b/src/ui/widget/scalar.cpp new file mode 100644 index 000000000..ae90e4a0f --- /dev/null +++ b/src/ui/widget/scalar.cpp @@ -0,0 +1,217 @@ +/** + * \brief Scalar Widget - A labelled text box, with spin buttons and optional + * icon or suffix, for entering arbitrary number values. + * + * Authors: + * Carl Hetherington <inkscape@carlh.net> + * Derek P. Moore <derekm@hackunix.org> + * Bryce Harrington <bryce@bryceharrington.org> + * + * Copyright (C) 2004 Carl Hetherington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "scalar.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Construct a Scalar Widget. + * + * \param label Label. + * \param suffix Suffix, placed after the widget (defaults to ""). + * \param icon Icon filename, placed before the label (defaults to ""). + * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label + * indicates the next character should be used for the + * mnemonic accelerator key (defaults to false). + */ +Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip, + Glib::ustring const &suffix, + Glib::ustring const &icon, + bool mnemonic) + : Labelled(label, tooltip, new Gtk::SpinButton(), suffix, icon, mnemonic), + setProgrammatically(false) +{ +} + +/** + * Construct a Scalar Widget. + * + * \param label Label. + * \param digits Number of decimal digits to display. + * \param suffix Suffix, placed after the widget (defaults to ""). + * \param icon Icon filename, placed before the label (defaults to ""). + * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label + * indicates the next character should be used for the + * mnemonic accelerator key (defaults to false). + */ +Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip, + unsigned digits, + Glib::ustring const &suffix, + Glib::ustring const &icon, + bool mnemonic) + : Labelled(label, tooltip, new Gtk::SpinButton(0.0, digits), suffix, icon, mnemonic), + setProgrammatically(false) +{ +} + +/** + * Construct a Scalar Widget. + * + * \param label Label. + * \param adjust Adjustment to use for the SpinButton. + * \param digits Number of decimal digits to display (defaults to 0). + * \param suffix Suffix, placed after the widget (defaults to ""). + * \param icon Icon filename, placed before the label (defaults to ""). + * \param mnemonic Mnemonic toggle; if true, an underscore (_) in the label + * indicates the next character should be used for the + * mnemonic accelerator key (defaults to true). + */ +Scalar::Scalar(Glib::ustring const &label, Glib::ustring const &tooltip, + Gtk::Adjustment &adjust, + unsigned digits, + Glib::ustring const &suffix, + Glib::ustring const &icon, + bool mnemonic) + : Labelled(label, tooltip, new Gtk::SpinButton(adjust, 0.0, digits), suffix, icon, mnemonic), + setProgrammatically(false) +{ +} + +/** Fetches the precision of the spin buton */ +unsigned +Scalar::getDigits() const +{ + g_assert(_widget != NULL); + return static_cast<Gtk::SpinButton*>(_widget)->get_digits(); +} + +/** Gets the current step ingrement used by the spin button */ +double +Scalar::getStep() const +{ + g_assert(_widget != NULL); + double step, page; + static_cast<Gtk::SpinButton*>(_widget)->get_increments(step, page); + return step; +} + +/** Gets the current page increment used by the spin button */ +double +Scalar::getPage() const +{ + g_assert(_widget != NULL); + double step, page; + static_cast<Gtk::SpinButton*>(_widget)->get_increments(step, page); + return page; +} + +/** Gets the minimum range value allowed for the spin button */ +double +Scalar::getRangeMin() const +{ + g_assert(_widget != NULL); + double min, max; + static_cast<Gtk::SpinButton*>(_widget)->get_range(min, max); + return min; +} + +/** Gets the maximum range value allowed for the spin button */ +double +Scalar::getRangeMax() const +{ + g_assert(_widget != NULL); + double min, max; + static_cast<Gtk::SpinButton*>(_widget)->get_range(min, max); + return max; +} + +/** Get the value in the spin_button . */ +double +Scalar::getValue() const +{ + g_assert(_widget != NULL); + return static_cast<Gtk::SpinButton*>(_widget)->get_value(); +} + +/** Get the value spin_button represented as an integer. */ +int +Scalar::getValueAsInt() const +{ + g_assert(_widget != NULL); + return static_cast<Gtk::SpinButton*>(_widget)->get_value_as_int(); +} + + +/** Sets the precision to be displayed by the spin button */ +void +Scalar::setDigits(unsigned digits) +{ + g_assert(_widget != NULL); + static_cast<Gtk::SpinButton*>(_widget)->set_digits(digits); +} + +/** Sets the step and page increments for the spin button */ +void +Scalar::setIncrements(double step, double page) +{ + g_assert(_widget != NULL); + static_cast<Gtk::SpinButton*>(_widget)->set_increments(step, page); +} + +/** Sets the minimum and maximum range allowed for the spin button */ +void +Scalar::setRange(double min, double max) +{ + g_assert(_widget != NULL); + static_cast<Gtk::SpinButton*>(_widget)->set_range(min, max); +} + +/** Sets the value of the spin button */ +void +Scalar::setValue(double value) +{ + g_assert(_widget != NULL); + setProgrammatically = true; // callback is supposed to reset back, if it cares + static_cast<Gtk::SpinButton*>(_widget)->set_value(value); +} + +/** Manually forces an update of the spin button */ +void +Scalar::update() { + g_assert(_widget != NULL); + static_cast<Gtk::SpinButton*>(_widget)->update(); +} + + + +/** Signal raised when the spin button's value changes */ +Glib::SignalProxy0<void> +Scalar::signal_value_changed() +{ + return static_cast<Gtk::SpinButton*>(_widget)->signal_value_changed(); +} + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/scalar.h b/src/ui/widget/scalar.h new file mode 100644 index 000000000..8ce72d949 --- /dev/null +++ b/src/ui/widget/scalar.h @@ -0,0 +1,86 @@ +/** + * \brief Scalar Widget - A labelled text box, with spin buttons and optional + * icon or suffix, for entering arbitrary number values. + * + * Authors: + * Carl Hetherington <inkscape@carlh.net> + * Derek P. Moore <derekm@hackunix.org> + * Bryce Harrington <bryce@bryceharrington.org> + * + * Copyright (C) 2004 Carl Hetherington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_SCALAR_H +#define INKSCAPE_UI_WIDGET_SCALAR_H + +#include <gtkmm/adjustment.h> +#include <gtkmm/spinbutton.h> + +#include "labelled.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Scalar : public Labelled +{ +public: + Scalar(Glib::ustring const &label, + Glib::ustring const &tooltip, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + bool mnemonic = true); + Scalar(Glib::ustring const &label, + Glib::ustring const &tooltip, + unsigned digits, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + bool mnemonic = true); + Scalar(Glib::ustring const &label, + Glib::ustring const &tooltip, + Gtk::Adjustment &adjust, + unsigned digits = 0, + Glib::ustring const &suffix = "", + Glib::ustring const &icon = "", + bool mnemonic = true); + + unsigned getDigits() const; + double getStep() const; + double getPage() const; + double getRangeMin() const; + double getRangeMax() const; + bool getSnapToTicks() const; + double getValue() const; + int getValueAsInt() const; + + void setDigits(unsigned digits); + void setIncrements(double step, double page); + void setRange(double min, double max); + void setValue(double value); + + void update(); + + Glib::SignalProxy0<void> signal_value_changed(); + + bool setProgrammatically; // true if the value was set by setValue, not changed by the user; + // if a callback checks it, it must reset it back to false +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_SCALAR_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp new file mode 100644 index 000000000..c808289b2 --- /dev/null +++ b/src/ui/widget/selected-style.cpp @@ -0,0 +1,977 @@ +/** + * \brief Selected style indicator (fill, stroke, opacity) + * + * Author: + * buliabyak@gmail.com + * + * Copyright (C) 2005 author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +#include "selected-style.h" + +#include "widgets/spw-utilities.h" +#include "ui/widget/color-preview.h" + +#include "selection.h" +#include "desktop-handles.h" +#include "style.h" +#include "desktop-style.h" +#include "sp-linear-gradient-fns.h" +#include "sp-radial-gradient-fns.h" +#include "sp-pattern.h" +#include "dialogs/object-properties.h" +#include "xml/repr.h" +#include "document.h" +#include "widgets/widget-sizes.h" +#include "widgets/spinbutton-events.h" +#include "svg/svg.h" +#include "svg/css-ostringstream.h" +#include "helper/units.h" + +static gdouble const _sw_presets[] = { 32 , 16 , 10 , 8 , 6 , 4 , 3 , 2 , 1.5 , 1 , 0.75 , 0.5 , 0.25 , 0.1 }; +static gchar* const _sw_presets_str[] = {"32", "16", "10", "8", "6", "4", "3", "2", "1.5", "1", "0.75", "0.5", "0.25", "0.1"}; + +static void +ss_selection_changed (Inkscape::Selection *, gpointer data) +{ + Inkscape::UI::Widget::SelectedStyle *ss = (Inkscape::UI::Widget::SelectedStyle *) data; + ss->update(); +} + +static void +ss_selection_modified (Inkscape::Selection *selection, guint flags, gpointer data) +{ + ss_selection_changed (selection, data); +} + +static void +ss_subselection_changed (gpointer dragger, gpointer data) +{ + ss_selection_changed (NULL, data); +} + +namespace Inkscape { +namespace UI { +namespace Widget { + +SelectedStyle::SelectedStyle(bool layout) + : _desktop (NULL), + + _table(2, 6), + _fill_label (_("F:")), + _stroke_label (_("S:")), + _opacity_label (_("O:")), + _fill_place (), + _stroke_place (), + + _fill_flag_place (), + _stroke_flag_place (), + + _opacity_place (), + _opacity_adjustment (1.0, 0.0, 1.0, 0.01, 0.1), + _opacity_sb (0.02, 2), + + _stroke (), + _stroke_width (""), + + _opacity_blocked (false), + + _popup_px(_sw_group), + _popup_pt(_sw_group), + _popup_mm(_sw_group), + + _sw_unit(NULL), + + _tooltips () +{ + _fill_label.set_alignment(0.0, 0.5); + _fill_label.set_padding(0, 0); + _stroke_label.set_alignment(0.0, 0.5); + _stroke_label.set_padding(0, 0); + _opacity_label.set_alignment(0.0, 0.5); + _opacity_label.set_padding(0, 0); + + _table.set_col_spacings (2); + _table.set_row_spacings (0); + + for (int i = SS_FILL; i <= SS_STROKE; i++) { + + _na[i].set_markup (_("N/A")); + sp_set_font_size_smaller (GTK_WIDGET(_na[i].gobj())); + _na[i].show_all(); + __na[i] = (_("Nothing selected")); + + _none[i].set_markup (_("None")); + sp_set_font_size_smaller (GTK_WIDGET(_none[i].gobj())); + _none[i].show_all(); + __none[i] = (i == SS_FILL)? (_("No fill")) : (_("No stroke")); + + _pattern[i].set_markup (_("Pattern")); + sp_set_font_size_smaller (GTK_WIDGET(_pattern[i].gobj())); + _pattern[i].show_all(); + __pattern[i] = (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke")); + + _lgradient[i].set_markup (_("L Gradient")); + sp_set_font_size_smaller (GTK_WIDGET(_lgradient[i].gobj())); + _lgradient[i].show_all(); + __lgradient[i] = (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke")); + + _rgradient[i].set_markup (_("R Gradient")); + sp_set_font_size_smaller (GTK_WIDGET(_rgradient[i].gobj())); + _rgradient[i].show_all(); + __rgradient[i] = (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke")); + + _many[i].set_markup (_("Different")); + sp_set_font_size_smaller (GTK_WIDGET(_many[i].gobj())); + _many[i].show_all(); + __many[i] = (i == SS_FILL)? (_("Different fills")) : (_("Different strokes")); + + _unset[i].set_markup (_("Unset")); + sp_set_font_size_smaller (GTK_WIDGET(_unset[i].gobj())); + _unset[i].show_all(); + __unset[i] = (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke")); + + _color_preview[i] = new Inkscape::UI::Widget::ColorPreview (0); + __color[i] = (i == SS_FILL)? (_("Flat color fill")) : (_("Flat color stroke")); + + // TRANSLATOR COMMENT: A means "Averaged" + _averaged[i].set_markup (_("<b>a</b>")); + sp_set_font_size_smaller (GTK_WIDGET(_averaged[i].gobj())); + _averaged[i].show_all(); + __averaged[i] = (i == SS_FILL)? (_("Fill is averaged over selected objects")) : (_("Stroke is averaged over selected objects")); + + // TRANSLATOR COMMENT: M means "Multiple" + _multiple[i].set_markup (_("<b>m</b>")); + sp_set_font_size_smaller (GTK_WIDGET(_multiple[i].gobj())); + _multiple[i].show_all(); + __multiple[i] = (i == SS_FILL)? (_("Multiple selected objects have the same fill")) : (_("Multiple selected objects have the same stroke")); + + _popup_edit[i].add(*(new Gtk::Label((i == SS_FILL)? _("Edit fill...") : _("Edit stroke..."), 0.0, 0.5))); + _popup_edit[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_edit : &SelectedStyle::on_stroke_edit )); + + _popup_lastused[i].add(*(new Gtk::Label(_("Last set color"), 0.0, 0.5))); + _popup_lastused[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_lastused : &SelectedStyle::on_stroke_lastused )); + + _popup_lastselected[i].add(*(new Gtk::Label(_("Last selected color"), 0.0, 0.5))); + _popup_lastselected[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_lastselected : &SelectedStyle::on_stroke_lastselected )); + + _popup_invert[i].add(*(new Gtk::Label(_("Invert"), 0.0, 0.5))); + _popup_invert[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_invert : &SelectedStyle::on_stroke_invert )); + + _popup_white[i].add(*(new Gtk::Label(_("White"), 0.0, 0.5))); + _popup_white[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_white : &SelectedStyle::on_stroke_white )); + + _popup_black[i].add(*(new Gtk::Label(_("Black"), 0.0, 0.5))); + _popup_black[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_black : &SelectedStyle::on_stroke_black )); + + _popup_copy[i].add(*(new Gtk::Label(_("Copy color"), 0.0, 0.5))); + _popup_copy[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_copy : &SelectedStyle::on_stroke_copy )); + + _popup_paste[i].add(*(new Gtk::Label(_("Paste color"), 0.0, 0.5))); + _popup_paste[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_paste : &SelectedStyle::on_stroke_paste )); + + _popup_swap[i].add(*(new Gtk::Label(_("Swap fill and stroke"), 0.0, 0.5))); + _popup_swap[i].signal_activate().connect(sigc::mem_fun(*this, + &SelectedStyle::on_fillstroke_swap)); + + _popup_opaque[i].add(*(new Gtk::Label((i == SS_FILL)? _("Make fill opaque") : _("Make stroke opaque"), 0.0, 0.5))); + _popup_opaque[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_opaque : &SelectedStyle::on_stroke_opaque )); + + //TRANSLATORS COMMENT: unset is a verb here + _popup_unset[i].add(*(new Gtk::Label((i == SS_FILL)? _("Unset fill") : _("Unset stroke"), 0.0, 0.5))); + _popup_unset[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_unset : &SelectedStyle::on_stroke_unset )); + + _popup_remove[i].add(*(new Gtk::Label((i == SS_FILL)? _("Remove fill") : _("Remove stroke"), 0.0, 0.5))); + _popup_remove[i].signal_activate().connect(sigc::mem_fun(*this, + (i == SS_FILL)? &SelectedStyle::on_fill_remove : &SelectedStyle::on_stroke_remove )); + + _popup[i].attach(_popup_edit[i], 0,1, 0,1); + _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 1,2); + _popup[i].attach(_popup_lastused[i], 0,1, 2,3); + _popup[i].attach(_popup_lastselected[i], 0,1, 3,4); + _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 4,5); + _popup[i].attach(_popup_invert[i], 0,1, 5,6); + _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 6,7); + _popup[i].attach(_popup_white[i], 0,1, 7,8); + _popup[i].attach(_popup_black[i], 0,1, 8,9); + _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 9,10); + _popup[i].attach(_popup_copy[i], 0,1, 10,11); + _popup_copy[i].set_sensitive(false); + _popup[i].attach(_popup_paste[i], 0,1, 11,12); + _popup[i].attach(_popup_swap[i], 0,1, 12,13); + _popup[i].attach(*(new Gtk::SeparatorMenuItem()), 0,1, 13,14); + _popup[i].attach(_popup_opaque[i], 0,1, 14,15); + _popup[i].attach(_popup_unset[i], 0,1, 15,16); + _popup[i].attach(_popup_remove[i], 0,1, 16,17); + _popup[i].show_all(); + + _mode[i] = SS_NA; + } + + { + _popup_px.add(*(new Gtk::Label(_("px"), 0.0, 0.5))); + _popup_px.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_px)); + _popup_sw.attach(_popup_px, 0,1, 0,1); + + _popup_pt.add(*(new Gtk::Label(_("pt"), 0.0, 0.5))); + _popup_pt.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_pt)); + _popup_sw.attach(_popup_pt, 0,1, 1,2); + + _popup_mm.add(*(new Gtk::Label(_("mm"), 0.0, 0.5))); + _popup_mm.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_mm)); + _popup_sw.attach(_popup_mm, 0,1, 2,3); + + _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, 3,4); + + for (guint i = 0; i < G_N_ELEMENTS(_sw_presets_str); ++i) { + Gtk::MenuItem *mi = Gtk::manage(new Gtk::MenuItem()); + mi->add(*(new Gtk::Label(_sw_presets_str[i], 0.0, 0.5))); + mi->signal_activate().connect(sigc::bind<int>(sigc::mem_fun(*this, &SelectedStyle::on_popup_preset), i)); + _popup_sw.attach(*mi, 0,1, 4+i, 5+i); + } + + guint i = G_N_ELEMENTS(_sw_presets_str) + 5; + + _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, i,i+1); + + _popup_sw_remove.add(*(new Gtk::Label(_("Remove"), 0.0, 0.5))); + _popup_sw_remove.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_stroke_remove)); + _popup_sw.attach(_popup_sw_remove, 0,1, i+1,i+2); + + _popup_sw.show_all(); + } + + _fill_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_fill_click)); + _stroke_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_stroke_click)); + _opacity_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_click)); + _stroke_width_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_sw_click)); + + _opacity_sb.signal_populate_popup().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_menu)); + _opacity_sb.signal_value_changed().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_changed)); + + _fill_place.add(_na[SS_FILL]); + _tooltips.set_tip(_fill_place, __na[SS_FILL]); + + _stroke_place.add(_na[SS_STROKE]); + _tooltips.set_tip(_stroke_place, __na[SS_STROKE]); + + _stroke.pack_start(_stroke_place); + _stroke_width_place.add(_stroke_width); + _stroke.pack_start(_stroke_width_place, Gtk::PACK_SHRINK); + + _opacity_sb.set_adjustment(_opacity_adjustment); + sp_set_font_size_smaller (GTK_WIDGET(_opacity_sb.gobj())); + _opacity_sb.set_size_request (SELECTED_STYLE_SB_WIDTH, -1); + _opacity_sb.set_sensitive (false); + + _table.attach(_fill_label, 0,1, 0,1, Gtk::SHRINK, Gtk::SHRINK); + _table.attach(_stroke_label, 0,1, 1,2, Gtk::SHRINK, Gtk::SHRINK); + + _table.attach(_fill_flag_place, 1,2, 0,1, Gtk::SHRINK, Gtk::SHRINK); + _table.attach(_stroke_flag_place, 1,2, 1,2, Gtk::SHRINK, Gtk::SHRINK); + + _table.attach(_fill_place, 2,3, 0,1); + _table.attach(_stroke, 2,3, 1,2); + + _opacity_place.add(_opacity_label); + _table.attach(_opacity_place, 4,5, 0,2, Gtk::SHRINK, Gtk::SHRINK); + _table.attach(_opacity_sb, 5,6, 0,2, Gtk::SHRINK, Gtk::SHRINK); + + pack_start(_table, true, true, 2); + + set_size_request (SELECTED_STYLE_WIDTH, -1); + + sp_set_font_size_smaller (GTK_WIDGET(_opacity_label.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_opacity_sb.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_fill_place.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_fill_flag_place.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_stroke_place.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_stroke_flag_place.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_stroke_width.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_fill_label.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_stroke_label.gobj())); +} + +SelectedStyle::~SelectedStyle() +{ + selection_changed_connection->disconnect(); + delete selection_changed_connection; + selection_modified_connection->disconnect(); + delete selection_modified_connection; + subselection_changed_connection->disconnect(); + delete subselection_changed_connection; + + for (int i = SS_FILL; i <= SS_STROKE; i++) { + delete _color_preview[i]; + } +} + +void +SelectedStyle::setDesktop(SPDesktop *desktop) +{ + _desktop = desktop; + gtk_object_set_data (GTK_OBJECT(_opacity_sb.gobj()), "dtw", _desktop->canvas); + + Inkscape::Selection *selection = SP_DT_SELECTION (desktop); + + selection_changed_connection = new sigc::connection (selection->connectChanged( + sigc::bind ( + sigc::ptr_fun(&ss_selection_changed), + this ) + )); + selection_modified_connection = new sigc::connection (selection->connectModified( + sigc::bind ( + sigc::ptr_fun(&ss_selection_modified), + this ) + )); + subselection_changed_connection = new sigc::connection (desktop->connectToolSubselectionChanged( + sigc::bind ( + sigc::ptr_fun(&ss_subselection_changed), + this ) + )); + + //_sw_unit = (SPUnit *) SP_DT_NAMEDVIEW(desktop)->doc_units; +} + +void SelectedStyle::on_fill_remove() { + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, "fill", "none"); + sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_stroke_remove() { + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, "stroke", "none"); + sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_unset() { + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_unset_property (css, "fill"); + sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_stroke_unset() { + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_unset_property (css, "stroke"); + sp_desktop_set_style (_desktop, css, true, false); // do not write to current, to preserve current color + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_opaque() { + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, "fill-opacity", "1"); + sp_desktop_set_style (_desktop, css, true); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_stroke_opaque() { + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, "stroke-opacity", "1"); + sp_desktop_set_style (_desktop, css, true); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_lastused() { + SPCSSAttr *css = sp_repr_css_attr_new (); + guint32 color = sp_desktop_get_color(_desktop, true); + gchar c[64]; + sp_svg_write_color (c, 64, color); + sp_repr_css_set_property (css, "fill", c); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_stroke_lastused() { + SPCSSAttr *css = sp_repr_css_attr_new (); + guint32 color = sp_desktop_get_color(_desktop, false); + gchar c[64]; + sp_svg_write_color (c, 64, color); + sp_repr_css_set_property (css, "stroke", c); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_lastselected() { + SPCSSAttr *css = sp_repr_css_attr_new (); + gchar c[64]; + sp_svg_write_color (c, 64, _lastselected[SS_FILL]); + sp_repr_css_set_property (css, "fill", c); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_stroke_lastselected() { + SPCSSAttr *css = sp_repr_css_attr_new (); + gchar c[64]; + sp_svg_write_color (c, 64, _lastselected[SS_STROKE]); + sp_repr_css_set_property (css, "stroke", c); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_invert() { + SPCSSAttr *css = sp_repr_css_attr_new (); + guint32 color = _thisselected[SS_FILL]; + gchar c[64]; + if (_mode[SS_FILL] != SS_COLOR) return; + sp_svg_write_color (c, 64, + SP_RGBA32_U_COMPOSE( + (255 - SP_RGBA32_R_U(color)), + (255 - SP_RGBA32_G_U(color)), + (255 - SP_RGBA32_B_U(color)), + SP_RGBA32_A_U(color) + ) + ); + sp_repr_css_set_property (css, "fill", c); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_stroke_invert() { + SPCSSAttr *css = sp_repr_css_attr_new (); + guint32 color = _thisselected[SS_STROKE]; + gchar c[64]; + if (_mode[SS_STROKE] != SS_COLOR) return; + sp_svg_write_color (c, 64, + SP_RGBA32_U_COMPOSE( + (255 - SP_RGBA32_R_U(color)), + (255 - SP_RGBA32_G_U(color)), + (255 - SP_RGBA32_B_U(color)), + SP_RGBA32_A_U(color) + ) + ); + sp_repr_css_set_property (css, "stroke", c); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_white() { + SPCSSAttr *css = sp_repr_css_attr_new (); + gchar c[64]; + sp_svg_write_color (c, 64, 0xffffffff); + sp_repr_css_set_property (css, "fill", c); + sp_repr_css_set_property (css, "fill-opacity", "1"); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_stroke_white() { + SPCSSAttr *css = sp_repr_css_attr_new (); + gchar c[64]; + sp_svg_write_color (c, 64, 0xffffffff); + sp_repr_css_set_property (css, "stroke", c); + sp_repr_css_set_property (css, "stroke-opacity", "1"); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_black() { + SPCSSAttr *css = sp_repr_css_attr_new (); + gchar c[64]; + sp_svg_write_color (c, 64, 0x000000ff); + sp_repr_css_set_property (css, "fill", c); + sp_repr_css_set_property (css, "fill-opacity", "1.0"); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_stroke_black() { + SPCSSAttr *css = sp_repr_css_attr_new (); + gchar c[64]; + sp_svg_write_color (c, 64, 0x000000ff); + sp_repr_css_set_property (css, "stroke", c); + sp_repr_css_set_property (css, "stroke-opacity", "1.0"); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_copy() { + if (_mode[SS_FILL] == SS_COLOR) { + gchar c[64]; + sp_svg_write_color (c, 64, _thisselected[SS_FILL]); + Glib::ustring text; + text += c; + if (!text.empty()) { + Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get(); + refClipboard->set_text(text); + } + } +} + +void SelectedStyle::on_stroke_copy() { + if (_mode[SS_STROKE] == SS_COLOR) { + gchar c[64]; + sp_svg_write_color (c, 64, _thisselected[SS_STROKE]); + Glib::ustring text; + text += c; + if (!text.empty()) { + Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get(); + refClipboard->set_text(text); + } + } +} + +void SelectedStyle::on_fill_paste() { + Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get(); + Glib::ustring const text = refClipboard->wait_for_text(); + + if (!text.empty()) { + guint32 color = sp_svg_read_color(text.c_str(), 0x000000ff); // impossible value, as SVG color cannot have opacity + if (color == 0x000000ff) // failed to parse color string + return; + + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, "fill", text.c_str()); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); + } +} + +void SelectedStyle::on_stroke_paste() { + Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get(); + Glib::ustring const text = refClipboard->wait_for_text(); + + if (!text.empty()) { + guint32 color = sp_svg_read_color(text.c_str(), 0x000000ff); // impossible value, as SVG color cannot have opacity + if (color == 0x000000ff) // failed to parse color string + return; + + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, "stroke", text.c_str()); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); + } +} + +void SelectedStyle::on_fillstroke_swap() { + SPCSSAttr *css = sp_repr_css_attr_new (); + + switch (_mode[SS_FILL]) { + case SS_NA: + case SS_MANY: + break; + case SS_NONE: + sp_repr_css_set_property (css, "stroke", "none"); + break; + case SS_UNSET: + sp_repr_css_unset_property (css, "stroke"); + break; + case SS_COLOR: + gchar c[64]; + sp_svg_write_color (c, 64, _thisselected[SS_FILL]); + sp_repr_css_set_property (css, "stroke", c); + break; + case SS_LGRADIENT: + case SS_RGRADIENT: + case SS_PATTERN: + sp_repr_css_set_property (css, "stroke", _paintserver_id[SS_FILL].c_str()); + break; + } + + switch (_mode[SS_STROKE]) { + case SS_NA: + case SS_MANY: + break; + case SS_NONE: + sp_repr_css_set_property (css, "fill", "none"); + break; + case SS_UNSET: + sp_repr_css_unset_property (css, "fill"); + break; + case SS_COLOR: + gchar c[64]; + sp_svg_write_color (c, 64, _thisselected[SS_STROKE]); + sp_repr_css_set_property (css, "fill", c); + break; + case SS_LGRADIENT: + case SS_RGRADIENT: + case SS_PATTERN: + sp_repr_css_set_property (css, "fill", _paintserver_id[SS_STROKE].c_str()); + break; + } + + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void SelectedStyle::on_fill_edit() { + sp_object_properties_fill(); +} + +void SelectedStyle::on_stroke_edit() { + sp_object_properties_stroke(); +} + +bool +SelectedStyle::on_fill_click(GdkEventButton *event) +{ + if (event->button == 1) { // click, open fill&stroke + sp_object_properties_fill(); + } else if (event->button == 3) { // right-click, popup menu + _popup[SS_FILL].popup(event->button, event->time); + } else if (event->button == 2) { // middle click, toggle none/lastcolor + if (_mode[SS_FILL] == SS_NONE) { + on_fill_lastused(); + } else { + on_fill_remove(); + } + } + return true; +} + +bool +SelectedStyle::on_stroke_click(GdkEventButton *event) +{ + if (event->button == 1) { // click, open fill&stroke + sp_object_properties_stroke(); + } else if (event->button == 3) { // right-click, popup menu + _popup[SS_STROKE].popup(event->button, event->time); + } else if (event->button == 2) { // middle click, toggle none/lastcolor + if (_mode[SS_STROKE] == SS_NONE) { + on_stroke_lastused(); + } else { + on_stroke_remove(); + } + } + return true; +} + +bool +SelectedStyle::on_sw_click(GdkEventButton *event) +{ + if (event->button == 1) { // click, open fill&stroke + sp_object_properties_stroke_style (); + } else if (event->button == 3) { // right-click, popup menu + _popup_sw.popup(event->button, event->time); + } else if (event->button == 2) { // middle click, toggle none/lastwidth? + // + } + return true; +} + +bool +SelectedStyle::on_opacity_click(GdkEventButton *event) +{ + if (event->button == 2) { // middle click + const char* opacity = _opacity_sb.get_value() < 0.5? "0.5" : (_opacity_sb.get_value() == 1? "0" : "1"); + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, "opacity", opacity); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT (_desktop)); + return true; + } + + return false; +} + +void SelectedStyle::on_popup_px() { + _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_PX)); + update(); +} +void SelectedStyle::on_popup_pt() { + _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_PT)); + update(); +} +void SelectedStyle::on_popup_mm() { + _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_MM)); + update(); +} + +void SelectedStyle::on_popup_preset(int i) { + SPCSSAttr *css = sp_repr_css_attr_new (); + gdouble w; + if (_sw_unit) { + w = sp_units_get_pixels (_sw_presets[i], *_sw_unit); + } else { + w = _sw_presets[i]; + } + Inkscape::CSSOStringStream os; + os << w; + sp_repr_css_set_property (css, "stroke-width", os.str().c_str()); + sp_desktop_set_style (_desktop, css, true); + sp_repr_css_attr_unref (css); + sp_document_done (SP_DT_DOCUMENT(_desktop)); +} + +void +SelectedStyle::update() +{ + if (_desktop == NULL) + return; + + // create temporary style + SPStyle *query = sp_style_new (); + + for (int i = SS_FILL; i <= SS_STROKE; i++) { + Gtk::EventBox *place = (i == SS_FILL)? &_fill_place : &_stroke_place; + Gtk::EventBox *flag_place = (i == SS_FILL)? &_fill_flag_place : &_stroke_flag_place; + + place->remove(); + flag_place->remove(); + + _tooltips.unset_tip(*place); + _tooltips.unset_tip(*flag_place); + + _mode[i] = SS_NA; + _paintserver_id[i].clear(); + + _popup_copy[i].set_sensitive(false); + + // query style from desktop. This returns a result flag and fills query with the style of subselection, if any, or selection + int result = sp_desktop_query_style (_desktop, query, + (i == SS_FILL)? QUERY_STYLE_PROPERTY_FILL : QUERY_STYLE_PROPERTY_STROKE); + switch (result) { + case QUERY_STYLE_NOTHING: + place->add(_na[i]); + _tooltips.set_tip(*place, __na[i]); + _mode[i] = SS_NA; + break; + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + SPIPaint *paint; + if (i == SS_FILL) { + paint = &(query->fill); + } else { + paint = &(query->stroke); + } + if (paint->set && paint->type == SP_PAINT_TYPE_COLOR) { + guint32 color = sp_color_get_rgba32_falpha (&(paint->value.color), + SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value)); + _lastselected[i] = _thisselected[i]; + _thisselected[i] = color | 0xff; // only color, opacity === 1 + ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color); + _color_preview[i]->show_all(); + place->add(*_color_preview[i]); + gchar c_string[64]; + g_snprintf (c_string, 64, "%06x/%.3g", color >> 8, SP_RGBA32_A_F(color)); + _tooltips.set_tip(*place, __color[i] + ": " + c_string); + _mode[i] = SS_COLOR; + _popup_copy[i].set_sensitive(true); + + } else if (paint->set && paint->type == SP_PAINT_TYPE_PAINTSERVER) { + SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query); + + Inkscape::XML::Node *srepr = SP_OBJECT_REPR(server); + _paintserver_id[i] += "url(#"; + _paintserver_id[i] += srepr->attribute("id"); + _paintserver_id[i] += ")"; + + if (SP_IS_LINEARGRADIENT (server)) { + place->add(_lgradient[i]); + _tooltips.set_tip(*place, __lgradient[i]); + _mode[i] = SS_LGRADIENT; + } else if (SP_IS_RADIALGRADIENT (server)) { + place->add(_rgradient[i]); + _tooltips.set_tip(*place, __rgradient[i]); + _mode[i] = SS_RGRADIENT; + } else if (SP_IS_PATTERN (server)) { + place->add(_pattern[i]); + _tooltips.set_tip(*place, __pattern[i]); + _mode[i] = SS_PATTERN; + } + + } else if (paint->set && paint->type == SP_PAINT_TYPE_NONE) { + place->add(_none[i]); + _tooltips.set_tip(*place, __none[i]); + _mode[i] = SS_NONE; + } else if (!paint->set) { + place->add(_unset[i]); + _tooltips.set_tip(*place, __unset[i]); + _mode[i] = SS_UNSET; + } + if (result == QUERY_STYLE_MULTIPLE_AVERAGED) { + flag_place->add(_averaged[i]); + _tooltips.set_tip(*flag_place, __averaged[i]); + } else if (result == QUERY_STYLE_MULTIPLE_SAME) { + flag_place->add(_multiple[i]); + _tooltips.set_tip(*flag_place, __multiple[i]); + } + break; + case QUERY_STYLE_MULTIPLE_DIFFERENT: + place->add(_many[i]); + _tooltips.set_tip(*place, __many[i]); + _mode[i] = SS_MANY; + break; + default: + break; + } + } + +// Now query opacity + _tooltips.unset_tip(_opacity_place); + + int result = sp_desktop_query_style (_desktop, query, QUERY_STYLE_PROPERTY_MASTEROPACITY); + + switch (result) { + case QUERY_STYLE_NOTHING: + _tooltips.set_tip(_opacity_place, _("Nothing selected")); + _opacity_sb.set_sensitive(false); + break; + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + _tooltips.set_tip(_opacity_place, _("Master opacity")); + _opacity_blocked = true; + _opacity_sb.set_sensitive(true); + _opacity_adjustment.set_value(SP_SCALE24_TO_FLOAT(query->opacity.value)); + _opacity_blocked = false; + break; + } + +// Now query stroke_width + int result_sw = sp_desktop_query_style (_desktop, query, QUERY_STYLE_PROPERTY_STROKEWIDTH); + switch (result_sw) { + case QUERY_STYLE_NOTHING: + _stroke_width.set_markup(""); + break; + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + { + double w; + if (_sw_unit) { + w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit); + } else { + w = query->stroke_width.computed; + } + { + gchar *str = g_strdup_printf(" %.3g", w); + _stroke_width.set_markup(str); + g_free (str); + } + { + gchar *str = g_strdup_printf(_("Stroke width: %.5g%s%s"), + w, + _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px", + (result_sw == QUERY_STYLE_MULTIPLE_AVERAGED)? + _(" (averaged)") : ""); + _tooltips.set_tip(_stroke_width_place, str); + g_free (str); + } + break; + } + default: + break; + } + + g_free (query); +} + +void SelectedStyle::opacity_0(void) {_opacity_sb.set_value(0);} +void SelectedStyle::opacity_025(void) {_opacity_sb.set_value(0.25);} +void SelectedStyle::opacity_05(void) {_opacity_sb.set_value(0.5);} +void SelectedStyle::opacity_075(void) {_opacity_sb.set_value(0.75);} +void SelectedStyle::opacity_1(void) {_opacity_sb.set_value(1.0);} + +void SelectedStyle::on_opacity_menu (Gtk::Menu *menu) { + + Glib::ListHandle<Gtk::Widget *> children = menu->get_children(); + for (Glib::ListHandle<Gtk::Widget *>::iterator iter = children.begin(); iter != children.end(); iter++) { + menu->remove(*(*iter)); + } + + { + Gtk::MenuItem *item = new Gtk::MenuItem; + item->add(*(new Gtk::Label(_("0 (transparent)"), 0, 0))); + item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_0 )); + menu->add(*item); + } + { + Gtk::MenuItem *item = new Gtk::MenuItem; + item->add(*(new Gtk::Label("0.25", 0, 0))); + item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_025 )); + menu->add(*item); + } + { + Gtk::MenuItem *item = new Gtk::MenuItem; + item->add(*(new Gtk::Label("0.5", 0, 0))); + item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_05 )); + menu->add(*item); + } + { + Gtk::MenuItem *item = new Gtk::MenuItem; + item->add(*(new Gtk::Label("0.75", 0, 0))); + item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_075 )); + menu->add(*item); + } + { + Gtk::MenuItem *item = new Gtk::MenuItem; + item->add(*(new Gtk::Label(_("1.0 (opaque)"), 0, 0))); + item->signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::opacity_1 )); + menu->add(*item); + } + + menu->show_all(); +} + +void SelectedStyle::on_opacity_changed () { + if (_opacity_blocked) + return; + _opacity_blocked = true; + SPCSSAttr *css = sp_repr_css_attr_new (); + Inkscape::CSSOStringStream os; + os << CLAMP (_opacity_adjustment.get_value(), 0.0, 1.0); + sp_repr_css_set_property (css, "opacity", os.str().c_str()); + sp_desktop_set_style (_desktop, css); + sp_repr_css_attr_unref (css); + sp_document_maybe_done (SP_DT_DOCUMENT (_desktop), "fillstroke:opacity"); + spinbutton_defocus(GTK_OBJECT(_opacity_sb.gobj())); + _opacity_blocked = false; +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/selected-style.h b/src/ui/widget/selected-style.h new file mode 100644 index 000000000..8f9c0fbf6 --- /dev/null +++ b/src/ui/widget/selected-style.h @@ -0,0 +1,212 @@ +/** + * \brief Selected style indicator (fill, stroke, opacity) + * + * Authors: + * buliabyak@gmail.com + * scislac@users.sf.net + * + * Copyright (C) 2005 authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_CURRENT_STYLE_H +#define INKSCAPE_UI_CURRENT_STYLE_H + +#include <gtkmm/table.h> +#include <gtkmm/label.h> +#include <gtkmm/box.h> +#include <gtkmm/eventbox.h> +#include <gtkmm/enums.h> +#include <gtkmm/menu.h> +#include <gtkmm/menuitem.h> +#include <gtkmm/adjustment.h> +#include <gtkmm/spinbutton.h> + +#include <sigc++/sigc++.h> + +#include <glibmm/i18n.h> + +#include <desktop.h> + +#include "button.h" + +class SPUnit; + +namespace Inkscape { +namespace UI { +namespace Widget { + +enum { + SS_NA, + SS_NONE, + SS_UNSET, + SS_PATTERN, + SS_LGRADIENT, + SS_RGRADIENT, + SS_MANY, + SS_COLOR +}; + +enum { + SS_FILL, + SS_STROKE +}; + +class SelectedStyle : public Gtk::HBox +{ +public: + SelectedStyle(bool layout = true); + + ~SelectedStyle(); + + void setDesktop(SPDesktop *desktop); + void update(); + +protected: + SPDesktop *_desktop; + + Gtk::Table _table; + + Gtk::Label _fill_label; + Gtk::Label _stroke_label; + Gtk::Label _opacity_label; + + Gtk::EventBox _fill_place; + Gtk::EventBox _stroke_place; + + Gtk::EventBox _fill_flag_place; + Gtk::EventBox _stroke_flag_place; + + Gtk::EventBox _opacity_place; + Gtk::Adjustment _opacity_adjustment; + Gtk::SpinButton _opacity_sb; + + Gtk::Label _na[2]; + Glib::ustring __na[2]; + + Gtk::Label _none[2]; + Glib::ustring __none[2]; + + Gtk::Label _pattern[2]; + Glib::ustring __pattern[2]; + + Gtk::Label _lgradient[2]; + Glib::ustring __lgradient[2]; + + Gtk::Label _rgradient[2]; + Glib::ustring __rgradient[2]; + + Gtk::Label _many[2]; + Glib::ustring __many[2]; + + Gtk::Label _unset[2]; + Glib::ustring __unset[2]; + + Gtk::Widget *_color_preview[2]; + Glib::ustring __color[2]; + + Gtk::Label _averaged[2]; + Glib::ustring __averaged[2]; + Gtk::Label _multiple[2]; + Glib::ustring __multiple[2]; + + Gtk::HBox _stroke; + Gtk::EventBox _stroke_width_place; + Gtk::Label _stroke_width; + + guint32 _lastselected[2]; + guint32 _thisselected[2]; + Glib::ustring _paintserver_id[2]; + + guint _mode[2]; + + sigc::connection *selection_changed_connection; + sigc::connection *selection_modified_connection; + sigc::connection *subselection_changed_connection; + + bool on_fill_click(GdkEventButton *event); + bool on_stroke_click(GdkEventButton *event); + bool on_opacity_click(GdkEventButton *event); + bool on_sw_click(GdkEventButton *event); + + bool _opacity_blocked; + void on_opacity_changed(); + void on_opacity_menu(Gtk::Menu *menu); + void opacity_0(); + void opacity_025(); + void opacity_05(); + void opacity_075(); + void opacity_1(); + + void on_fill_remove(); + void on_stroke_remove(); + void on_fill_lastused(); + void on_stroke_lastused(); + void on_fill_lastselected(); + void on_stroke_lastselected(); + void on_fill_unset(); + void on_stroke_unset(); + void on_fill_edit(); + void on_stroke_edit(); + void on_fillstroke_swap(); + void on_fill_invert(); + void on_stroke_invert(); + void on_fill_white(); + void on_stroke_white(); + void on_fill_black(); + void on_stroke_black(); + void on_fill_copy(); + void on_stroke_copy(); + void on_fill_paste(); + void on_stroke_paste(); + void on_fill_opaque(); + void on_stroke_opaque(); + + Gtk::Menu _popup[2]; + Gtk::MenuItem _popup_edit[2]; + Gtk::MenuItem _popup_lastused[2]; + Gtk::MenuItem _popup_lastselected[2]; + Gtk::MenuItem _popup_invert[2]; + Gtk::MenuItem _popup_white[2]; + Gtk::MenuItem _popup_black[2]; + Gtk::MenuItem _popup_copy[2]; + Gtk::MenuItem _popup_paste[2]; + Gtk::MenuItem _popup_swap[2]; + Gtk::MenuItem _popup_opaque[2]; + Gtk::MenuItem _popup_unset[2]; + Gtk::MenuItem _popup_remove[2]; + + Gtk::Menu _popup_sw; + Gtk::RadioButtonGroup _sw_group; + Gtk::RadioMenuItem _popup_px; + void on_popup_px(); + Gtk::RadioMenuItem _popup_pt; + void on_popup_pt(); + Gtk::RadioMenuItem _popup_mm; + void on_popup_mm(); + void on_popup_preset(int i); + Gtk::MenuItem _popup_sw_remove; + + SPUnit *_sw_unit; + + Gtk::Tooltips _tooltips; +}; + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_BUTTON_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp new file mode 100644 index 000000000..5d4623c19 --- /dev/null +++ b/src/ui/widget/style-swatch.cpp @@ -0,0 +1,244 @@ +/** + * \brief Static style swatch (fill, stroke, opacity) + * + * Author: + * buliabyak@gmail.com + * + * Copyright (C) 2005 author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "style-swatch.h" + +#include "widgets/spw-utilities.h" +#include "ui/widget/color-preview.h" + +#include "style.h" +#include "sp-linear-gradient-fns.h" +#include "sp-radial-gradient-fns.h" +#include "sp-pattern.h" +#include "xml/repr.h" +#include "widgets/widget-sizes.h" +#include "helper/units.h" + +enum { + SS_FILL, + SS_STROKE +}; + + +namespace Inkscape { +namespace UI { +namespace Widget { + +StyleSwatch::StyleSwatch(SPCSSAttr *css) + : _css (NULL), + + _table(2, 6), + + _sw_unit(NULL), + + _tooltips () +{ + _label[SS_FILL].set_markup(_("F:")); + _label[SS_STROKE].set_markup(_("S:")); + + for (int i = SS_FILL; i <= SS_STROKE; i++) { + _label[i].set_alignment(0.0, 0.5); + _label[i].set_padding(0, 0); + + _color_preview[i] = new Inkscape::UI::Widget::ColorPreview (0); + } + + _opacity_value.set_alignment(0.0, 0.5); + _opacity_value.set_padding(0, 0); + + _table.set_col_spacings (2); + _table.set_row_spacings (0); + + _stroke.pack_start(_place[SS_STROKE]); + _stroke_width_place.add(_stroke_width); + _stroke.pack_start(_stroke_width_place, Gtk::PACK_SHRINK); + + _table.attach(_label[SS_FILL], 0,1, 0,1, Gtk::SHRINK, Gtk::SHRINK); + _table.attach(_label[SS_STROKE], 0,1, 1,2, Gtk::SHRINK, Gtk::SHRINK); + + _table.attach(_place[SS_FILL], 1,2, 0,1); + _table.attach(_stroke, 1,2, 1,2); + + _opacity_place.add(_opacity_value); + _table.attach(_opacity_place, 2,3, 0,2, Gtk::SHRINK, Gtk::SHRINK); + + pack_start(_table, true, true, 0); + + set_size_request (STYLE_SWATCH_WIDTH, -1); + + sp_set_font_size_smaller (GTK_WIDGET(_opacity_value.gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_stroke_width.gobj())); + for (int i = SS_FILL; i <= SS_STROKE; i++) { + sp_set_font_size_smaller (GTK_WIDGET(_value[i].gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_place[i].gobj())); + sp_set_font_size_smaller (GTK_WIDGET(_label[i].gobj())); + } + + setStyle (css); +} + +StyleSwatch::~StyleSwatch() +{ + if (_css) + sp_repr_css_attr_unref (_css); + + for (int i = SS_FILL; i <= SS_STROKE; i++) { + delete _color_preview[i]; + } +} + +void +StyleSwatch::setStyle(SPCSSAttr *css) +{ + if (_css) + sp_repr_css_attr_unref (_css); + _css = sp_repr_css_attr_new(); + sp_repr_css_merge(_css, css); + + gchar const *css_string = sp_repr_css_write_string (_css); + SPStyle *temp_spstyle = sp_style_new(); + sp_style_merge_from_style_string (temp_spstyle, css_string); + + setStyle (temp_spstyle); + + sp_style_unref (temp_spstyle); +} + +void +StyleSwatch::setStyle(SPStyle *query) +{ + _place[SS_FILL].remove(); + _place[SS_STROKE].remove(); + + bool has_stroke = true; + + for (int i = SS_FILL; i <= SS_STROKE; i++) { + Gtk::EventBox *place = &(_place[i]); + + SPIPaint *paint; + if (i == SS_FILL) { + paint = &(query->fill); + } else { + paint = &(query->stroke); + } + + if (paint->set && paint->type == SP_PAINT_TYPE_COLOR) { + guint32 color = sp_color_get_rgba32_falpha (&(paint->value.color), + SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value)); + ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color); + _color_preview[i]->show_all(); + place->add(*_color_preview[i]); + gchar *tip; + if (i == SS_FILL) { + tip = g_strdup_printf ("Fill: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color)); + } else { + tip = g_strdup_printf ("Stroke: %06x/%.3g", color >> 8, SP_RGBA32_A_F(color)); + } + _tooltips.set_tip(*place, tip); + g_free (tip); + } else if (paint->set && paint->type == SP_PAINT_TYPE_PAINTSERVER) { + SPPaintServer *server = (i == SS_FILL)? SP_STYLE_FILL_SERVER (query) : SP_STYLE_STROKE_SERVER (query); + + if (SP_IS_LINEARGRADIENT (server)) { + _value[i].set_markup(_("L Gradient")); + place->add(_value[i]); + _tooltips.set_tip(*place, (i == SS_FILL)? (_("Linear gradient fill")) : (_("Linear gradient stroke"))); + } else if (SP_IS_RADIALGRADIENT (server)) { + _value[i].set_markup(_("R Gradient")); + place->add(_value[i]); + _tooltips.set_tip(*place, (i == SS_FILL)? (_("Radial gradient fill")) : (_("Radial gradient stroke"))); + } else if (SP_IS_PATTERN (server)) { + _value[i].set_markup(_("Pattern")); + place->add(_value[i]); + _tooltips.set_tip(*place, (i == SS_FILL)? (_("Pattern fill")) : (_("Pattern stroke"))); + } + + } else if (paint->set && paint->type == SP_PAINT_TYPE_NONE) { + _value[i].set_markup(_("None")); + place->add(_value[i]); + _tooltips.set_tip(*place, (i == SS_FILL)? (_("No fill")) : (_("No stroke"))); + if (i == SS_STROKE) has_stroke = false; + } else if (!paint->set) { + _value[i].set_markup(_("Unset")); + place->add(_value[i]); + _tooltips.set_tip(*place, (i == SS_FILL)? (_("Unset fill")) : (_("Unset stroke"))); + if (i == SS_STROKE) has_stroke = false; + } + } + +// Now query stroke_width + if (has_stroke) { + double w; + if (_sw_unit) { + w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit); + } else { + w = query->stroke_width.computed; + } + + { + gchar *str = g_strdup_printf(" %.3g", w); + _stroke_width.set_markup(str); + g_free (str); + } + { + gchar *str = g_strdup_printf(_("Stroke width: %.5g%s"), + w, + _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px"); + _tooltips.set_tip(_stroke_width_place, str); + g_free (str); + } + } else { + _tooltips.unset_tip(_stroke_width_place); + _stroke_width.set_markup (""); + } + + gdouble op = SP_SCALE24_TO_FLOAT(query->opacity.value); + if (op != 1) { + { + gchar *str; + if (op == 0) + str = g_strdup_printf(_("0:%.3g"), op); + else + str = g_strdup_printf(_("0:.%d"), (int) (op*10)); + _opacity_value.set_markup (str); + g_free (str); + } + { + gchar *str = g_strdup_printf(_("Opacity: %.3g"), op); + _tooltips.set_tip(_opacity_place, str); + g_free (str); + } + } else { + _tooltips.unset_tip(_opacity_place); + _opacity_value.set_markup (""); + } + + show_all(); +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/style-swatch.h b/src/ui/widget/style-swatch.h new file mode 100644 index 000000000..d78b3d64e --- /dev/null +++ b/src/ui/widget/style-swatch.h @@ -0,0 +1,88 @@ +/** + * \brief Static style swatch (fill, stroke, opacity) + * + * Author: + * buliabyak@gmail.com + * + * Copyright (C) 2005 author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_CURRENT_STYLE_H +#define INKSCAPE_UI_CURRENT_STYLE_H + +#include <gtkmm/table.h> +#include <gtkmm/label.h> +#include <gtkmm/box.h> +#include <gtkmm/eventbox.h> +#include <gtkmm/enums.h> + +#include <glibmm/i18n.h> + +#include <desktop.h> + +#include "button.h" + +class SPUnit; +class SPStyle; +class SPCSSAttr; + +namespace Inkscape { +namespace UI { +namespace Widget { + +class StyleSwatch : public Gtk::HBox +{ +public: + StyleSwatch (SPStyle *style); + StyleSwatch (SPCSSAttr *attr); + + ~StyleSwatch(); + + void setStyle(SPStyle *style); + void setStyle(SPCSSAttr *attr); + SPCSSAttr *getStyle(); + +protected: + SPCSSAttr *_css; + + Gtk::Table _table; + + Gtk::Label _label[2]; + + Gtk::EventBox _place[2]; + Gtk::EventBox _opacity_place; + + Gtk::Label _value[2]; + Gtk::Label _opacity_value; + + Gtk::Widget *_color_preview[2]; + Glib::ustring __color[2]; + + Gtk::HBox _stroke; + Gtk::EventBox _stroke_width_place; + Gtk::Label _stroke_width; + + SPUnit *_sw_unit; + + Gtk::Tooltips _tooltips; +}; + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_BUTTON_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/svg-canvas.cpp b/src/ui/widget/svg-canvas.cpp new file mode 100644 index 000000000..1ba49b7ec --- /dev/null +++ b/src/ui/widget/svg-canvas.cpp @@ -0,0 +1,92 @@ +/** \file + * Gtkmm facade/wrapper around SPCanvas. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 The Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> +#include "desktop.h" +#include "desktop-events.h" +#include "display/canvas-arena.h" +#include "display/display-forward.h" +#include "ui/widget/svg-canvas.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +SVGCanvas::SVGCanvas() +{ + void *canvas = gtk_type_new (sp_canvas_get_type ()); + _spcanvas = static_cast<SPCanvas*>(canvas); + _widget = Glib::wrap (static_cast<GtkWidget*> (canvas)); + _dt = 0; +} + +SVGCanvas::~SVGCanvas() +{ +} + +void +SVGCanvas::init (SPDesktop *dt) +{ + _dt = dt; + _widget->set_flags(Gtk::CAN_FOCUS); + + // Set background to white + Glib::RefPtr<Gtk::Style> style = _widget->get_style(); + style->set_bg(Gtk::STATE_NORMAL, style->get_white()); + _widget->set_style(style); + _widget->set_extension_events(Gdk::EXTENSION_EVENTS_ALL); + _widget->signal_event().connect(sigc::mem_fun(*this, &SVGCanvas::onEvent)); +} + +bool +SVGCanvas::onEvent (GdkEvent * ev) const +{ + g_assert (_dt); + + // Gdk::Event doesn't appear to be fully usable for this atm + if (ev->type == GDK_BUTTON_PRESS) { + // defocus any spinbuttons + _widget->grab_focus(); + } + + if ((ev->type == GDK_BUTTON_PRESS) && (ev->button.button == 3)) { + if (ev->button.state & GDK_SHIFT_MASK) { + sp_canvas_arena_set_sticky(SP_CANVAS_ARENA(_dt->drawing), true); + } else { + sp_canvas_arena_set_sticky(SP_CANVAS_ARENA(_dt->drawing), false); + } + } + + // The keypress events need to be passed to desktop handler explicitly, + // because otherwise the event contexts only receive keypresses when the mouse cursor + // is over the canvas. This redirection is only done for keypresses and only if there's no + // current item on the canvas, because item events and all mouse events are caught + // and passed on by the canvas acetate (I think). --bb + + if (ev->type == GDK_KEY_PRESS && !_spcanvas->current_item) { + return sp_desktop_root_handler(0, ev, _dt); + } + + return false; +} + +}}} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/svg-canvas.h b/src/ui/widget/svg-canvas.h new file mode 100644 index 000000000..cb8dc4013 --- /dev/null +++ b/src/ui/widget/svg-canvas.h @@ -0,0 +1,56 @@ +#ifndef __UI_WIDGET_SVGCANVAS_H__ +#define __UI_WIDGET_SVGCANVAS_H__ + +/** \file + * Gtkmm facade/wrapper around SPCanvas. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 The Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +struct SPCanvas; +struct SPDesktop; +namespace Gtk { class Widget; } +namespace Inkscape { + namespace UI { + namespace Widget { + +class SVGCanvas +{ +public: + SVGCanvas(); + ~SVGCanvas(); + void init (SPDesktop*); + Gtk::Widget& widget() const { return *_widget; } + SPCanvas* spobj() const { return _spcanvas; } + +protected: + Gtk::Widget *_widget; + SPCanvas *_spcanvas; + SPDesktop *_dt; + + bool onEvent (GdkEvent *) const; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/tolerance-slider.cpp b/src/ui/widget/tolerance-slider.cpp new file mode 100644 index 000000000..dbef74eaf --- /dev/null +++ b/src/ui/widget/tolerance-slider.cpp @@ -0,0 +1,142 @@ +/** \file + * + Implementation of tolerance slider widget. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2006 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/label.h> +#include <gtkmm/scale.h> + +#include "xml/repr.h" +#include "svg/stringstream.h" + +#include "inkscape.h" +#include "document.h" +#include "desktop-handles.h" +#include "sp-namedview.h" + +#include "registry.h" +#include "tolerance-slider.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +//=================================================== + +//--------------------------------------------------- + + + +//==================================================== + +ToleranceSlider::ToleranceSlider() +: _hbox(0) +{ +} + +ToleranceSlider::~ToleranceSlider() +{ + if (_hbox) delete _hbox; + _scale_changed_connection.disconnect(); +} + +void +ToleranceSlider::init (const Glib::ustring& label1, const Glib::ustring& label2, const Glib::ustring& tip, const Glib::ustring& key, Registry& wr) +{ + _hbox = new Gtk::HBox; + Gtk::Label *theLabel1 = manage (new Gtk::Label (label1)); + _hbox->add (*theLabel1); + _hscale = manage (new Gtk::HScale (0.4, 50.1, 0.1)); + _hscale->set_draw_value (true); + _hscale->set_value_pos (Gtk::POS_RIGHT); + _hscale->set_size_request (100, -1); + _hbox->add (*_hscale); + Gtk::Label *theLabel2 = manage (new Gtk::Label (label2)); + _hbox->add (*theLabel2); + _key = key; + _scale_changed_connection = _hscale->signal_value_changed().connect (sigc::mem_fun (*this, &ToleranceSlider::update)); + _wr = ≀ +} + +void +ToleranceSlider::setValue (double val, bool is_absolute) +{ + _hscale->set_value (val); + Gtk::Adjustment *adj = _hscale->get_adjustment(); + if (is_absolute) + { + adj->set_lower (0.4); + adj->set_upper (50.1); + adj->set_step_increment (0.1); + } + else + { + adj->set_lower (1.0); + adj->set_upper (51.0); + adj->set_step_increment (1.0); + } + update(); +} + +void +ToleranceSlider::setLimits (double theMin, double theMax) +{ + _hscale->set_range (theMin, theMax); + _hscale->get_adjustment()->set_step_increment (1); +} + +void +ToleranceSlider::update() +{ + if (_wr->isUpdating()) + return; + + SPDesktop *dt = SP_ACTIVE_DESKTOP; + if (!dt) + return; + + Inkscape::SVGOStringStream os; + os << _hscale->get_value(); + + _wr->setUpdating (true); + + SPDocument *doc = SP_DT_DOCUMENT(dt); + gboolean saved = sp_document_get_undo_sensitive (doc); + sp_document_set_undo_sensitive (doc, FALSE); + Inkscape::XML::Node *repr = SP_OBJECT_REPR (SP_DT_NAMEDVIEW(dt)); + repr->setAttribute(_key.c_str(), os.str().c_str()); + doc->rroot->setAttribute("sodipodi:modified", "true"); + sp_document_set_undo_sensitive (doc, saved); + sp_document_done (doc); + + _wr->setUpdating (false); +} + + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/tolerance-slider.h b/src/ui/widget/tolerance-slider.h new file mode 100644 index 000000000..2eeacb403 --- /dev/null +++ b/src/ui/widget/tolerance-slider.h @@ -0,0 +1,61 @@ +/** \file + * \brief + * + * This widget is part of the Document properties dialog. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2006 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_ +#define INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_ + + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Registry; +class ToleranceSlider { +public: + ToleranceSlider(); + ~ToleranceSlider(); + void init (const Glib::ustring& label1, + const Glib::ustring& label2, + const Glib::ustring& tip, + const Glib::ustring& key, + Registry& wr); + void setValue (double, bool); + void setLimits (double, double); + Gtk::HBox* _hbox; + +protected: + void on_scale_changed(); + void update(); + sigc::connection _scale_changed_connection; + Gtk::HScale *_hscale; + Registry *_wr; + Glib::ustring _key; +}; + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_TOLERANCE_SLIDER__H_ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/toolbox.cpp b/src/ui/widget/toolbox.cpp new file mode 100644 index 000000000..e90a58b6e --- /dev/null +++ b/src/ui/widget/toolbox.cpp @@ -0,0 +1,269 @@ +/** + * \brief Toolbox Widget - A detachable toolbar for buttons and other widgets. + * + * Author: + * Derek P. Moore <derekm@hackunix.org> + * + * Copyright (C) 2004 Derek P. Moore + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtkmm/radioaction.h> +#include <gtk/gtkmain.h> +#include "ui/widget/toolbox.h" +#include "path-prefix.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +Toolbox::Toolbox(Gtk::Toolbar *toolbar, + Gtk::Orientation orientation) + : HandleBox(toolbar) +{ + init_actions(); + init_orientation(orientation); + init_style(toolbar->get_toolbar_style()); +} + +Toolbox::Toolbox(Gtk::Toolbar *toolbar, + Gtk::ToolbarStyle style, + Gtk::Orientation orientation) + : HandleBox(toolbar) +{ + init_actions(); + init_orientation(orientation); + init_style(style); +} + +Gtk::Toolbar& +Toolbox::get_toolbar() +{ + return static_cast<Gtk::Toolbar&>(*_widget); +} + +static Glib::ustring +get_uidir_filename(char const *basename_utf8) +{ + char *const ret_str = g_build_filename(INKSCAPE_UIDIR, basename_utf8, NULL); + Glib::ustring const ret(ret_str); + g_free(ret_str); + return ret; +} + +void +Toolbox::init_actions() +{ + _action_grp = Gtk::ActionGroup::create(); + + Gtk::RadioAction::Group icons; + _action_grp->add(Gtk::RadioAction::create(icons, "Icons", "Icons Only"), + sigc::mem_fun(*this, &Toolbox::on_change_style_icons)); + _action_grp->add(Gtk::RadioAction::create(icons, "Text", "Text Only"), + sigc::mem_fun(*this, &Toolbox::on_change_style_text)); + _action_grp->add(Gtk::RadioAction::create(icons, "Both", "Text Below Icons"), + sigc::mem_fun(*this, &Toolbox::on_change_style_both)); + _action_grp->add(Gtk::RadioAction::create(icons, "BothHoriz", "Text Beside Icons"), + sigc::mem_fun(*this, &Toolbox::on_change_style_both_horiz)); + + _detach_grp = Gtk::ActionGroup::create(); + + Gtk::RadioAction::Group orient; + _detach_grp->add(Gtk::RadioAction::create(orient, "OrientHoriz", "Horizontal"), + sigc::mem_fun(*this, &Toolbox::on_change_orient_horiz)); + _detach_grp->add(Gtk::RadioAction::create(orient, "OrientVert", "Vertical"), + sigc::mem_fun(*this, &Toolbox::on_change_orient_vert)); + + _detach_grp->add(Gtk::ToggleAction::create("ShowArrow", "Show Arrow", + Glib::ustring(), true), + sigc::mem_fun(*this, &Toolbox::on_show_arrow)); + + _ui_mgr = Gtk::UIManager::create(); + _ui_mgr->insert_action_group(_action_grp); + _ui_mgr->insert_action_group(_detach_grp); + _ui_mgr->add_ui_from_file(get_uidir_filename("toolbox.xml")); + + _context_menu = static_cast<Gtk::Menu*>(_ui_mgr->get_widget("/ToolboxMenu")); + + static_cast<Gtk::Toolbar*>(_widget)->signal_popup_context_menu() + .connect(sigc::mem_fun(*this, &Toolbox::on_popup_context_menu)); + + _detach_grp->set_sensitive(false); +} + +void +Toolbox::init_orientation(Gtk::Orientation const &orientation) +{ + static_cast<Gtk::Toolbar*>(_widget)->set_orientation(orientation); + if (orientation == Gtk::ORIENTATION_VERTICAL) { + set_handle_position(Gtk::POS_TOP); + } + switch (orientation) { + case Gtk::ORIENTATION_HORIZONTAL: { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz")) + ->set_active(); + break; + } + case Gtk::ORIENTATION_VERTICAL: { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert")) + ->set_active(); + break; + } + } +} + +void +Toolbox::init_style(Gtk::ToolbarStyle const &style) +{ + switch (style) { + case Gtk::TOOLBAR_ICONS: { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Icons")) + ->activate(); + break; + } + case Gtk::TOOLBAR_TEXT: { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Text")) + ->activate(); + break; + } + case Gtk::TOOLBAR_BOTH: { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Both")) + ->activate(); + break; + } + case Gtk::TOOLBAR_BOTH_HORIZ: { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("BothHoriz")) + ->activate(); + break; + } + } +} + +bool +Toolbox::on_popup_context_menu(int x, int y, int button) +{ + (void)x; + (void)y; + _context_menu->popup(button, gtk_get_current_event_time()); + return true; +} + +void +Toolbox::on_child_attached(Gtk::Widget *widget) +{ + (void)widget; + Gtk::Toolbar *toolbar = static_cast<Gtk::Toolbar*>(_widget); + + if (!(toolbar->get_show_arrow())) { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow")) + ->activate(); + } + + if (get_handle_position() == Gtk::POS_LEFT + && toolbar->get_orientation() != Gtk::ORIENTATION_HORIZONTAL) { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz")) + ->activate(); + } else if (get_handle_position() == Gtk::POS_TOP + && toolbar->get_orientation() != Gtk::ORIENTATION_VERTICAL) { + Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert")) + ->activate(); + } + + _detach_grp->set_sensitive(false); +} + +void +Toolbox::on_child_detached(Gtk::Widget *widget) +{ + (void)widget; + _detach_grp->set_sensitive(true); + + Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow")) + ->set_active(false); +} + +void +Toolbox::on_change_style_icons() +{ + Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Icons")); + if (action->get_active()) { + static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_ICONS); + } +} + +void +Toolbox::on_change_style_text() +{ + Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Text")); + if (action->get_active()) { + static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_TEXT); + } +} + +void +Toolbox::on_change_style_both() +{ + Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("Both")); + if (action->get_active()) { + static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_BOTH); + } +} + +void +Toolbox::on_change_style_both_horiz() +{ + Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_action_grp->get_action("BothHoriz")); + if (action->get_active()) { + static_cast<Gtk::Toolbar*>(_widget)->set_toolbar_style(Gtk::TOOLBAR_BOTH_HORIZ); + } +} + +void +Toolbox::on_change_orient_horiz() +{ + Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientHoriz")); + if (action->get_active()) { + static_cast<Gtk::Toolbar*>(_widget)->set_orientation(Gtk::ORIENTATION_HORIZONTAL); + } +} + +void +Toolbox::on_change_orient_vert() +{ + Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("OrientVert")); + if (action->get_active()) { + static_cast<Gtk::Toolbar*>(_widget)->set_orientation(Gtk::ORIENTATION_VERTICAL); + } +} + +void +Toolbox::on_show_arrow() +{ + Glib::RefPtr<Gtk::RadioAction> action = Glib::RefPtr<Gtk::RadioAction>::cast_static(_detach_grp->get_action("ShowArrow")); + Gtk::Toolbar *toolbar = static_cast<Gtk::Toolbar*>(_widget); + if (action->get_active()) { + toolbar->set_show_arrow(true); + } else { + toolbar->set_show_arrow(false); + } +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/toolbox.h b/src/ui/widget/toolbox.h new file mode 100644 index 000000000..9c4e18909 --- /dev/null +++ b/src/ui/widget/toolbox.h @@ -0,0 +1,73 @@ +/** + * \brief Toolbox Widget - A detachable toolbar for buttons and other widgets. + * + * Author: + * Derek P. Moore <derekm@hackunix.org> + * + * Copyright (C) 2004 Derek P. Moore + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_TOOLBOX_H +#define INKSCAPE_UI_WIDGET_TOOLBOX_H + +#include <gtkmm/toolbar.h> +#include <gtkmm/menu.h> +#include <gtkmm/action.h> +#include <gtkmm/uimanager.h> +#include "handlebox.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Toolbox : public HandleBox +{ +public: + Toolbox(Gtk::Toolbar *toolbar, + Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL); + Toolbox(Gtk::Toolbar *toolbar, + Gtk::ToolbarStyle style, + Gtk::Orientation orientation = Gtk::ORIENTATION_HORIZONTAL); + + Gtk::Toolbar& get_toolbar(); + +protected: + Gtk::Menu *_context_menu; + + Glib::RefPtr<Gtk::ActionGroup> _action_grp; + Glib::RefPtr<Gtk::ActionGroup> _detach_grp; + Glib::RefPtr<Gtk::UIManager> _ui_mgr; + + void init_actions(); + void init_orientation(Gtk::Orientation const &orientation); + void init_style(Gtk::ToolbarStyle const &style); + bool on_popup_context_menu(int x, int y, int button); + void on_child_attached(Gtk::Widget *widget); + void on_child_detached(Gtk::Widget *widget); + void on_change_style_icons(); + void on_change_style_text(); + void on_change_style_both(); + void on_change_style_both_horiz(); + void on_change_orient_horiz(); + void on_change_orient_vert(); + void on_show_arrow(); +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_TOOLBOX_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/unit-menu.cpp b/src/ui/widget/unit-menu.cpp new file mode 100644 index 000000000..b4271762c --- /dev/null +++ b/src/ui/widget/unit-menu.cpp @@ -0,0 +1,181 @@ +/** + * \brief Unit Menu Widget - A drop down menu for choosing unit types. + * + * Author: + * Bryce Harrington <bryce@bryceharrington.org> + * + * Copyright (C) 2004 Bryce Harrington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <cmath> + +#include "unit-menu.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Construct a UnitMenu + * + */ +UnitMenu::UnitMenu() : _type(UNIT_TYPE_NONE) +{ + set_active(0); +} + +UnitMenu::~UnitMenu() { +} + +/** Adds the unit type to the widget. This extracts the corresponding + units from the unit map matching the given type, and appends them + to the dropdown widget. It causes the primary unit for the given + unit_type to be selected. */ +bool +UnitMenu::setUnitType(UnitType unit_type) +{ + /* Expand the unit widget with unit entries from the unit table */ + UnitTable::UnitMap m = _unit_table.units(unit_type); + UnitTable::UnitMap::iterator iter = m.begin(); + while(iter != m.end()) { + Glib::ustring text = (*iter).first; + append_text(text); + ++iter; + } + _type = unit_type; + set_active_text(_unit_table.primary(unit_type)); + + return true; +} + +/** Returns the Unit object corresponding to the current selection + in the dropdown widget */ +Unit +UnitMenu::getUnit() const { + if (get_active_text() == "") { + g_assert(_type != UNIT_TYPE_NONE); + return _unit_table.getUnit(_unit_table.primary(_type)); + } + return _unit_table.getUnit(get_active_text()); +} + +/** Sets the dropdown widget to the given unit abbreviation. + Returns true if the unit was selectable, false if not + (i.e., if the unit was not present in the widget) */ +bool +UnitMenu::setUnit(Glib::ustring const & unit) { + // TODO: Determine if 'unit' is available in the dropdown. + // If not, return false + + set_active_text(unit); + return true; +} + +/** Returns the abbreviated unit name of the selected unit */ +Glib::ustring +UnitMenu::getUnitAbbr() const { + if (get_active_text() == "") { + return ""; + } + return getUnit().abbr; +} + +/** Returns the UnitType of the selected unit */ +UnitType +UnitMenu::getUnitType() const { + return getUnit().type; +} + +/** Returns the unit factor for the selected unit */ +double +UnitMenu::getUnitFactor() const +{ + return getUnit().factor; +} + +/** Returns the recommended number of digits for displaying + * numbers of this unit type. + */ +int +UnitMenu::getDefaultDigits() const +{ + return getUnit().defaultDigits(); +} + +/** Returns the recommended step size in spin buttons + * displaying units of this type + */ +double +UnitMenu::getDefaultStep() const +{ + int factor_digits = -1*int(log10(getUnit().factor)); + return pow(10.0, factor_digits); +} + +/** Returns the recommended page size (when hitting pgup/pgdn) + * in spin buttons displaying units of this type + */ +double +UnitMenu::getDefaultPage() const +{ + return 10 * getDefaultStep(); +} + +/** + * Returns the conversion factor required to convert values + * of the currently selected unit into units of type + * new_unit_abbr. + */ +double +UnitMenu::getConversion(Glib::ustring const &new_unit_abbr, Glib::ustring const &old_unit_abbr) const +{ + double old_factor = getUnit().factor; + if (old_unit_abbr != "no_unit") + old_factor = _unit_table.getUnit(old_unit_abbr).factor; + Unit new_unit = _unit_table.getUnit(new_unit_abbr); + + // Catch the case of zero or negative unit factors (error!) + if (old_factor < 0.0000001 || + new_unit.factor < 0.0000001) { + // TODO: Should we assert here? + return 0.00; + } + + return old_factor / new_unit.factor; +} + +/** Returns true if the selected unit is not dimensionless + * (false for %, true for px, pt, cm, etc) + */ +bool +UnitMenu::isAbsolute() const { + return getUnitType() != UNIT_TYPE_DIMENSIONLESS; +} + +/** Returns true if the selected unit is radial (deg or rad) + */ +bool +UnitMenu::isRadial() const { + return getUnitType() == UNIT_TYPE_RADIAL; +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/unit-menu.h b/src/ui/widget/unit-menu.h new file mode 100644 index 000000000..60a9702b4 --- /dev/null +++ b/src/ui/widget/unit-menu.h @@ -0,0 +1,70 @@ +/** + * \brief Unit Menu Widget - A drop down menu for choosing unit types. + * + * Author: + * Bryce Harrington <bryce@bryceharrington.org> + * + * Copyright (C) 2004 Bryce Harrington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_UNIT_H +#define INKSCAPE_UI_WIDGET_UNIT_H + +#include "combo-text.h" +#include "util/units.h" + +using namespace Inkscape::Util; + +namespace Inkscape { +namespace UI { +namespace Widget { + +class UnitMenu : public ComboText +{ +public: + UnitMenu(); + virtual ~UnitMenu(); + + bool setUnitType(UnitType unit_type); + + bool setUnit(Glib::ustring const &unit); + + Unit getUnit() const; + Glib::ustring getUnitAbbr() const; + UnitType getUnitType() const; + double getUnitFactor() const; + + int getDefaultDigits() const; + double getDefaultStep() const; + double getDefaultPage() const; + + double getConversion(Glib::ustring const &new_unit_abbr, Glib::ustring const &old_unit_abbr = "no_unit") const; + + bool isAbsolute() const; + bool isRadial() const; + + UnitTable &getUnitTable() {return _unit_table;} + +protected: + UnitTable _unit_table; + UnitType _type; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_UNIT_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/zoom-status.cpp b/src/ui/widget/zoom-status.cpp new file mode 100644 index 000000000..e7320102c --- /dev/null +++ b/src/ui/widget/zoom-status.cpp @@ -0,0 +1,127 @@ +/** \file + * Gtkmm facade/wrapper around zoom_status code that formerly lived + * in desktop-widget.cpp + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * Lauris Kaplinski <lauris@kaplinski.com> + * MenTaLguY <mental@rydia.net> + * bulia byak <buliabyak@users.sf.net> + * + * Copyright (C) 2005 Ralf Stephan + * Copyright (C) 2004 MenTaLguY + * Copyright (C) 1999-2002 Lauris Kaplinski + * Copyright (C) 2000-2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "ui/widget/zoom-status.h" +#include "desktop.h" +#include "desktop-handles.h" +#include "widgets/spw-utilities.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +ZoomStatus::ZoomStatus() + : _adj(0.0, -1.0, 1.0, 0.1, 0.1) +{ + _dt = 0; + _upd_f = false; + + property_numeric() = false; + property_update_policy() = Gtk::UPDATE_ALWAYS; + sp_set_font_size_smaller(static_cast<GtkWidget*>((void*)gobj())); +} + +ZoomStatus::~ZoomStatus() +{ + _dt = 0; +} + +void +ZoomStatus::init(SPDesktop *dt) +{ + _dt = dt; + property_digits() = 4; + _adj.set_value(0.0); + _adj.set_lower(log(SP_DESKTOP_ZOOM_MIN)/log(2.0)); + _adj.set_upper(log(SP_DESKTOP_ZOOM_MAX)/log(2.0)); + _adj.set_step_increment(0.1); + _adj.set_page_increment(0.1); + set_adjustment(_adj); +} + +void +ZoomStatus::update() +{ + if (!_dt) return; + _upd_f = true; + set_value(log(_dt->current_zoom())/log(2.0)); + _upd_f = false; +} + +inline double +value_to_display(double value) +{ + return floor(pow(2, value) * 100.0 + 0.5); +} + +inline double +display_to_value(double value) +{ + return log(value / 100.0) / log(2.0); +} + +int +ZoomStatus::on_input(double *new_val) +{ + double new_scrolled = get_value(); + double new_typed = atof(get_text().c_str()); + + if (value_to_display(new_scrolled) == new_typed) + { // the new value is set by scrolling + *new_val = new_scrolled; + } else { // the new value is typed in + *new_val = display_to_value(new_typed); + } + + return true; +} + +bool +ZoomStatus::on_output() +{ + gchar b[64]; + g_snprintf(b, 64, "%4.0f%%", value_to_display(get_value())); + set_text(b); + return true; +} + +void +ZoomStatus::on_value_changed() +{ + if (_upd_f) return; + _upd_f = true; + g_assert(_dt); + double zoom_factor = pow(2, get_value()); + NR::Rect const d =_dt->get_display_area(); + _dt->zoom_absolute(d.midpoint()[NR::X], d.midpoint()[NR::Y], zoom_factor); + gtk_widget_grab_focus(static_cast<GtkWidget*>((void*)_dt->canvas)); /// \todo this no love song + _upd_f = false; +} + +}}} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/zoom-status.h b/src/ui/widget/zoom-status.h new file mode 100644 index 000000000..58d595329 --- /dev/null +++ b/src/ui/widget/zoom-status.h @@ -0,0 +1,61 @@ +#ifndef __UI_WIDGET_ZOOMSTATUS_H__ +#define __UI_WIDGET_ZOOMSTATUS_H__ + +/** \file + * Enhanced spinbutton. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 The Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/adjustment.h> +#include <gtkmm/spinbutton.h> + +struct SPDesktop; + +namespace Gtk { class Widget; } +namespace Inkscape { + namespace UI { + namespace Widget { + +class ZoomStatus : public Gtk::SpinButton +{ +public: + ZoomStatus(); + ~ZoomStatus(); + + void init (SPDesktop*); + void update(); + +protected: + Gtk::Adjustment _adj; + SPDesktop *_dt; + bool _upd_f; + + virtual int on_input (double*); + virtual bool on_output(); + virtual void on_value_changed(); +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +#endif + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : |
