summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorLiam P. White <inkscapebronyat-signgmaildotcom>2014-03-28 01:36:41 +0000
committerLiam P. White <inkscapebronyat-signgmaildotcom>2014-03-28 01:36:41 +0000
commitc1ecda53e4ce811681e6545f6158eb48c4a983a0 (patch)
tree064de4eb4815f49ed736bc9c52c3b3d78251a61a /src/ui
parentUpdate to trunk (diff)
parentFix make check (diff)
downloadinkscape-c1ecda53e4ce811681e6545f6158eb48c4a983a0.tar.gz
inkscape-c1ecda53e4ce811681e6545f6158eb48c4a983a0.zip
Update to trunk
(bzr r13090.1.35)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/CMakeLists.txt7
-rw-r--r--src/ui/dialog/Makefile_insert5
-rw-r--r--src/ui/dialog/arrange-tab.h54
-rw-r--r--src/ui/dialog/dialog-manager.cpp4
-rw-r--r--src/ui/dialog/grid-arrange-tab.cpp809
-rw-r--r--src/ui/dialog/grid-arrange-tab.h154
-rw-r--r--src/ui/dialog/polar-arrange-tab.cpp414
-rw-r--r--src/ui/dialog/polar-arrange-tab.h100
-rw-r--r--src/ui/dialog/tile.cpp878
-rw-r--r--src/ui/dialog/tile.h135
-rw-r--r--src/ui/tools/connector-tool.cpp53
-rw-r--r--src/ui/widget/Makefile_insert2
-rw-r--r--src/ui/widget/anchor-selector.cpp97
-rw-r--r--src/ui/widget/anchor-selector.h59
14 files changed, 1779 insertions, 992 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index c3e406e3f..7d80f1e36 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -69,6 +69,7 @@ set(ui_SRC
dialog/floating-behavior.cpp
dialog/font-substitution.cpp
dialog/glyphs.cpp
+ dialog/grid-arrange-tab.cpp
dialog/guides.cpp
dialog/icon-preview.cpp
dialog/inkscape-preferences.cpp
@@ -83,6 +84,7 @@ set(ui_SRC
dialog/object-attributes.cpp
dialog/object-properties.cpp
dialog/ocaldialogs.cpp
+ dialog/polar-arrange-tab.cpp
dialog/print-colors-preview-dialog.cpp
dialog/print.cpp
dialog/symbols.cpp
@@ -103,6 +105,7 @@ set(ui_SRC
# dialog/whiteboard-sharewithchat.cpp
# dialog/whiteboard-sharewithuser.cpp
+ widget/anchor-selector.cpp
widget/button.cpp
widget/color-picker.cpp
widget/color-preview.cpp
@@ -162,6 +165,7 @@ set(ui_SRC
dialog/aboutbox.h
dialog/align-and-distribute.h
+ dialog/arrange-tab.h
dialog/behavior.h
dialog/calligraphic-profile-rename.h
dialog/color-item.h
@@ -186,6 +190,7 @@ set(ui_SRC
dialog/font-substitution.h
dialog/glyphs.h
dialog/guides.h
+ dialog/grid-arrange-tab.h
dialog/icon-preview.h
dialog/inkscape-preferences.h
dialog/input.h
@@ -200,6 +205,7 @@ set(ui_SRC
dialog/object-properties.h
dialog/ocaldialogs.h
dialog/panel-dialog.h
+ dialog/polar-arrange-tab.h
dialog/pixelartdialog.h
dialog/print-colors-preview-dialog.h
dialog/print.h
@@ -259,6 +265,7 @@ set(ui_SRC
tools/tweak-tool.h
tools/zoom-tool.h
+ widget/anchor-selector.h
widget/attr-widget.h
widget/button.h
widget/color-picker.h
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
index 1cf667f2a..8a7a4a5dd 100644
--- a/src/ui/dialog/Makefile_insert
+++ b/src/ui/dialog/Makefile_insert
@@ -5,6 +5,7 @@ ink_common_sources += \
ui/dialog/aboutbox.h \
ui/dialog/align-and-distribute.cpp \
ui/dialog/align-and-distribute.h \
+ ui/dialog/arrange-tab.h \
ui/dialog/behavior.h \
ui/dialog/calligraphic-profile-rename.h \
ui/dialog/calligraphic-profile-rename.cpp \
@@ -50,6 +51,8 @@ ink_common_sources += \
ui/dialog/floating-behavior.h \
ui/dialog/glyphs.cpp \
ui/dialog/glyphs.h \
+ ui/dialog/grid-arrange-tab.h \
+ ui/dialog/grid-arrange-tab.cpp \
ui/dialog/guides.cpp \
ui/dialog/guides.h \
ui/dialog/icon-preview.cpp \
@@ -79,6 +82,8 @@ ink_common_sources += \
ui/dialog/object-properties.cpp \
ui/dialog/object-properties.h \
ui/dialog/panel-dialog.h \
+ ui/dialog/polar-arrange-tab.cpp \
+ ui/dialog/polar-arrange-tab.h \
ui/dialog/print.cpp \
ui/dialog/print.h \
ui/dialog/print-colors-preview-dialog.cpp \
diff --git a/src/ui/dialog/arrange-tab.h b/src/ui/dialog/arrange-tab.h
new file mode 100644
index 000000000..3ffe1ef4c
--- /dev/null
+++ b/src/ui/dialog/arrange-tab.h
@@ -0,0 +1,54 @@
+/**
+ * @brief Arrange tools base class
+ */
+/* Authors:
+ * * Declara Denis
+ * Copyright (C) 2012 Authors
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_ARRANGE_TAB_H
+#define INKSCAPE_UI_DIALOG_ARRANGE_TAB_H
+
+#include <gtkmm/box.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+/**
+ * This interface should be implemented by each arrange mode.
+ * The class is a Gtk::VBox and will be displayed as a tab in
+ * the dialog
+ */
+class ArrangeTab : public Gtk::VBox
+{
+public:
+ ArrangeTab() {};
+ virtual ~ArrangeTab() {};
+
+ /**
+ * Do the actual work! This method is invoked to actually arrange the
+ * selection
+ */
+ virtual void arrange() = 0;
+};
+
+} //namespace Dialog
+} //namespace UI
+} //namespace Inkscape
+
+
+#endif /* INKSCAPE_UI_DIALOG_ARRANGE_TAB_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:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index ddf41e0c8..ee11601f3 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -120,8 +120,8 @@ DialogManager::DialogManager() {
// registerFactory("PrintColorsPreviewDialog", &create<PrintColorsPreviewDialog, FloatingBehavior>);
registerFactory("SvgFontsDialog", &create<SvgFontsDialog, FloatingBehavior>);
registerFactory("Swatches", &create<SwatchesPanel, FloatingBehavior>);
+ registerFactory("TileDialog", &create<ArrangeDialog, FloatingBehavior>);
registerFactory("Symbols", &create<SymbolsDialog, FloatingBehavior>);
- registerFactory("TileDialog", &create<TileDialog, FloatingBehavior>);
registerFactory("Trace", &create<TraceDialog, FloatingBehavior>);
registerFactory("PixelArt", &create<PixelArtDialog, FloatingBehavior>);
registerFactory("Transformation", &create<Transformation, FloatingBehavior>);
@@ -156,8 +156,8 @@ DialogManager::DialogManager() {
// registerFactory("PrintColorsPreviewDialog", &create<PrintColorsPreviewDialog, DockBehavior>);
registerFactory("SvgFontsDialog", &create<SvgFontsDialog, DockBehavior>);
registerFactory("Swatches", &create<SwatchesPanel, DockBehavior>);
+ registerFactory("TileDialog", &create<ArrangeDialog, DockBehavior>);
registerFactory("Symbols", &create<SymbolsDialog, DockBehavior>);
- registerFactory("TileDialog", &create<TileDialog, DockBehavior>);
registerFactory("Trace", &create<TraceDialog, DockBehavior>);
registerFactory("PixelArt", &create<PixelArtDialog, DockBehavior>);
registerFactory("Transformation", &create<Transformation, DockBehavior>);
diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp
new file mode 100644
index 000000000..8c0a4dc66
--- /dev/null
+++ b/src/ui/dialog/grid-arrange-tab.cpp
@@ -0,0 +1,809 @@
+/*
+ * A simple dialog for creating grid type arrangements of selected objects
+ *
+ * Authors:
+ * Bob Jamison ( based off trace dialog)
+ * John Cliff
+ * Other dudes from The Inkscape Organization
+ * Abhishek Sharma
+ * Declara Denis
+ *
+ * Copyright (C) 2004 Bob Jamison
+ * Copyright (C) 2004 John Cliff
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+//#define DEBUG_GRID_ARRANGE 1
+
+#include "ui/dialog/grid-arrange-tab.h"
+#include <gtk/gtk.h> //for GTK_RESPONSE* types
+#include <glibmm/i18n.h>
+#include <gtkmm/stock.h>
+
+#if WITH_GTKMM_3_0
+# include <gtkmm/grid.h>
+#else
+# include <gtkmm/table.h>
+#endif
+
+#include <2geom/transforms.h>
+
+#include "verbs.h"
+#include "preferences.h"
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "selection.h"
+#include "document.h"
+#include "document-undo.h"
+#include "sp-item.h"
+#include "widgets/icon.h"
+#include "desktop.h"
+//#include "sp-item-transform.h" FIXME
+#include "ui/dialog/tile.h" // for Inkscape::UI::Dialog::ArrangeDialog
+
+/*
+ * Sort items by their x co-ordinates, taking account of y (keeps rows intact)
+ *
+ * <0 *elem1 goes before *elem2
+ * 0 *elem1 == *elem2
+ * >0 *elem1 goes after *elem2
+ */
+static int sp_compare_x_position(SPItem *first, SPItem *second)
+{
+ using Geom::X;
+ using Geom::Y;
+
+ Geom::OptRect a = first->documentVisualBounds();
+ Geom::OptRect b = second->documentVisualBounds();
+
+ if ( !a || !b ) {
+ // FIXME?
+ return 0;
+ }
+
+ double const a_height = a->dimensions()[Y];
+ double const b_height = b->dimensions()[Y];
+
+ bool a_in_b_vert = false;
+ if ((a->min()[Y] < b->min()[Y] + 0.1) && (a->min()[Y] > b->min()[Y] - b_height)) {
+ a_in_b_vert = true;
+ } else if ((b->min()[Y] < a->min()[Y] + 0.1) && (b->min()[Y] > a->min()[Y] - a_height)) {
+ a_in_b_vert = true;
+ } else if (b->min()[Y] == a->min()[Y]) {
+ a_in_b_vert = true;
+ } else {
+ a_in_b_vert = false;
+ }
+
+ if (!a_in_b_vert) {
+ return -1;
+ }
+ if (a_in_b_vert && a->min()[X] > b->min()[X]) {
+ return 1;
+ }
+ if (a_in_b_vert && a->min()[X] < b->min()[X]) {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Sort items by their y co-ordinates.
+ */
+static int sp_compare_y_position(SPItem *first, SPItem *second)
+{
+ Geom::OptRect a = first->documentVisualBounds();
+ Geom::OptRect b = second->documentVisualBounds();
+
+ if ( !a || !b ) {
+ // FIXME?
+ return 0;
+ }
+
+ if (a->min()[Geom::Y] > b->min()[Geom::Y]) {
+ return 1;
+ }
+ if (a->min()[Geom::Y] < b->min()[Geom::Y]) {
+ return -1;
+ }
+
+ return 0;
+}
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+
+//#########################################################################
+//## E V E N T S
+//#########################################################################
+
+/*
+ *
+ * This arranges the selection in a grid pattern.
+ *
+ */
+
+void GridArrangeTab::arrange()
+{
+
+ int cnt,row_cnt,col_cnt,a,row,col;
+ double grid_left,grid_top,col_width,row_height,paddingx,paddingy,width, height, new_x, new_y;
+ double total_col_width,total_row_height;
+ col_width = 0;
+ row_height = 0;
+ total_col_width=0;
+ total_row_height=0;
+
+ // check for correct numbers in the row- and col-spinners
+ on_col_spinbutton_changed();
+ on_row_spinbutton_changed();
+
+ // set padding to manual values
+ paddingx = XPadding.getValue("px");
+ paddingy = YPadding.getValue("px");
+
+ std::vector<double> row_heights;
+ std::vector<double> col_widths;
+ std::vector<double> row_ys;
+ std::vector<double> col_xs;
+
+ int NoOfCols = NoOfColsSpinner.get_value_as_int();
+ int NoOfRows = NoOfRowsSpinner.get_value_as_int();
+
+ width = 0;
+ for (a=0;a<NoOfCols; a++){
+ col_widths.push_back(width);
+ }
+
+ height = 0;
+ for (a=0;a<NoOfRows; a++){
+ row_heights.push_back(height);
+ }
+ grid_left = 99999;
+ grid_top = 99999;
+
+ SPDesktop *desktop = Parent->getDesktop();
+ sp_desktop_document(desktop)->ensureUpToDate();
+
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
+ const GSList *items = selection ? selection->itemList() : 0;
+ cnt=0;
+ for (; items != NULL; items = items->next) {
+ SPItem *item = SP_ITEM(items->data);
+ Geom::OptRect b = item->documentVisualBounds();
+ if (!b) {
+ continue;
+ }
+
+ width = b->dimensions()[Geom::X];
+ height = b->dimensions()[Geom::Y];
+
+ if (b->min()[Geom::X] < grid_left) {
+ grid_left = b->min()[Geom::X];
+ }
+ if (b->min()[Geom::Y] < grid_top) {
+ grid_top = b->min()[Geom::Y];
+ }
+ if (width > col_width) {
+ col_width = width;
+ }
+ if (height > row_height) {
+ row_height = height;
+ }
+ }
+
+
+ // require the sorting done before we can calculate row heights etc.
+
+ g_return_if_fail(selection);
+ const GSList *items2 = selection->itemList();
+ GSList *rev = g_slist_copy(const_cast<GSList *>(items2));
+ GSList *sorted = NULL;
+ rev = g_slist_sort(rev, (GCompareFunc) sp_compare_y_position);
+ sorted = g_slist_sort(rev, (GCompareFunc) sp_compare_x_position);
+
+
+ // Calculate individual Row and Column sizes if necessary
+
+
+ cnt=0;
+ const GSList *sizes = sorted;
+ for (; sizes != NULL; sizes = sizes->next) {
+ SPItem *item = SP_ITEM(sizes->data);
+ Geom::OptRect b = item->documentVisualBounds();
+ if (b) {
+ width = b->dimensions()[Geom::X];
+ height = b->dimensions()[Geom::Y];
+ if (width > col_widths[(cnt % NoOfCols)]) {
+ col_widths[(cnt % NoOfCols)] = width;
+ }
+ if (height > row_heights[(cnt / NoOfCols)]) {
+ row_heights[(cnt / NoOfCols)] = height;
+ }
+ }
+
+ cnt++;
+ }
+
+
+ /// Make sure the top and left of the grid dont move by compensating for align values.
+ if (RowHeightButton.get_active()){
+ grid_top = grid_top - (((row_height - row_heights[0]) / 2)*(VertAlign));
+ }
+ if (ColumnWidthButton.get_active()){
+ grid_left = grid_left - (((col_width - col_widths[0]) /2)*(HorizAlign));
+ }
+
+ #ifdef DEBUG_GRID_ARRANGE
+ g_print("\n cx = %f cy= %f gridleft=%f",cx,cy,grid_left);
+ #endif
+
+ // Calculate total widths and heights, allowing for columns and rows non uniformly sized.
+
+ if (ColumnWidthButton.get_active()){
+ total_col_width = col_width * NoOfCols;
+ col_widths.clear();
+ for (a=0;a<NoOfCols; a++){
+ col_widths.push_back(col_width);
+ }
+ } else {
+ for (a = 0; a < (int)col_widths.size(); a++)
+ {
+ total_col_width += col_widths[a] ;
+ }
+ }
+
+ if (RowHeightButton.get_active()){
+ total_row_height = row_height * NoOfRows;
+ row_heights.clear();
+ for (a=0;a<NoOfRows; a++){
+ row_heights.push_back(row_height);
+ }
+ } else {
+ for (a = 0; a < (int)row_heights.size(); a++)
+ {
+ total_row_height += row_heights[a] ;
+ }
+ }
+
+
+ Geom::OptRect sel_bbox = selection->visualBounds();
+ // Fit to bbox, calculate padding between rows accordingly.
+ if ( sel_bbox && !SpaceManualRadioButton.get_active() ){
+#ifdef DEBUG_GRID_ARRANGE
+g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_height,total_col_width, b.extent(Geom::X), b.extent(Geom::Y));
+#endif
+ paddingx = (sel_bbox->width() - total_col_width) / (NoOfCols -1);
+ paddingy = (sel_bbox->height() - total_row_height) / (NoOfRows -1);
+ }
+
+/*
+ Horizontal align - Left = 0
+ Centre = 1
+ Right = 2
+
+ Vertical align - Top = 0
+ Middle = 1
+ Bottom = 2
+
+ X position is calculated by taking the grids left co-ord, adding the distance to the column,
+ then adding 1/2 the spacing multiplied by the align variable above,
+ Y position likewise, takes the top of the grid, adds the y to the current row then adds the padding in to align it.
+
+*/
+
+ // Calculate row and column x and y coords required to allow for columns and rows which are non uniformly sized.
+
+ for (a=0;a<NoOfCols; a++){
+ if (a<1) col_xs.push_back(0);
+ else col_xs.push_back(col_widths[a-1]+paddingx+col_xs[a-1]);
+ }
+
+
+ for (a=0;a<NoOfRows; a++){
+ if (a<1) row_ys.push_back(0);
+ else row_ys.push_back(row_heights[a-1]+paddingy+row_ys[a-1]);
+ }
+
+ cnt=0;
+ for (row_cnt=0; ((sorted != NULL) && (row_cnt<NoOfRows)); row_cnt++) {
+
+ GSList *current_row = NULL;
+ for (col_cnt = 0; ((sorted != NULL) && (col_cnt<NoOfCols)); col_cnt++) {
+ current_row = g_slist_append (current_row, sorted->data);
+ sorted = sorted->next;
+ }
+
+ for (; current_row != NULL; current_row = current_row->next) {
+ SPItem *item=SP_ITEM(current_row->data);
+ Inkscape::XML::Node *repr = item->getRepr();
+ Geom::OptRect b = item->documentVisualBounds();
+ Geom::Point min;
+ if (b) {
+ width = b->dimensions()[Geom::X];
+ height = b->dimensions()[Geom::Y];
+ min = b->min();
+ } else {
+ width = height = 0;
+ min = Geom::Point(0, 0);
+ }
+
+ row = cnt / NoOfCols;
+ col = cnt % NoOfCols;
+
+ new_x = grid_left + (((col_widths[col] - width)/2)*HorizAlign) + col_xs[col];
+ new_y = grid_top + (((row_heights[row] - height)/2)*VertAlign) + row_ys[row];
+
+ // signs are inverted between x and y due to y inversion
+ Geom::Point move = Geom::Point(new_x - min[Geom::X], min[Geom::Y] - new_y);
+ Geom::Affine const affine = Geom::Affine(Geom::Translate(move));
+ item->set_i2d_affine(item->i2dt_affine() * affine);
+ item->doWriteTransform(repr, item->transform, NULL);
+ SP_OBJECT (current_row->data)->updateRepr();
+ cnt +=1;
+ }
+ g_slist_free (current_row);
+ }
+
+ DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_ARRANGE,
+ _("Arrange in a grid"));
+
+}
+
+
+//#########################################################################
+//## E V E N T S
+//#########################################################################
+
+/**
+ * changed value in # of columns spinbox.
+ */
+void GridArrangeTab::on_row_spinbutton_changed()
+{
+ // quit if run by the attr_changed listener
+ if (updating) {
+ return;
+ }
+
+ // in turn, prevent listener from responding
+ updating = true;
+ SPDesktop *desktop = Parent->getDesktop();
+
+ Inkscape::Selection *selection = desktop ? desktop->selection : 0;
+ g_return_if_fail( selection );
+
+ GSList const *items = selection->itemList();
+ int selcount = g_slist_length((GSList *)items);
+
+ double PerCol = ceil(selcount / NoOfColsSpinner.get_value());
+ NoOfRowsSpinner.set_value(PerCol);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble("/dialogs/gridtiler/NoOfCols", NoOfColsSpinner.get_value());
+ updating=false;
+}
+
+/**
+ * changed value in # of rows spinbox.
+ */
+void GridArrangeTab::on_col_spinbutton_changed()
+{
+ // quit if run by the attr_changed listener
+ if (updating) {
+ return;
+ }
+
+ // in turn, prevent listener from responding
+ updating = true;
+ SPDesktop *desktop = Parent->getDesktop();
+ Inkscape::Selection *selection = desktop ? desktop->selection : 0;
+ g_return_if_fail(selection);
+
+ GSList const *items = selection->itemList();
+ int selcount = g_slist_length((GSList *)items);
+
+ double PerRow = ceil(selcount / NoOfRowsSpinner.get_value());
+ NoOfColsSpinner.set_value(PerRow);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble("/dialogs/gridtiler/NoOfCols", PerRow);
+
+ updating=false;
+}
+
+/**
+ * changed value in x padding spinbox.
+ */
+void GridArrangeTab::on_xpad_spinbutton_changed()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble("/dialogs/gridtiler/XPad", XPadding.getValue("px"));
+
+}
+
+/**
+ * changed value in y padding spinbox.
+ */
+void GridArrangeTab::on_ypad_spinbutton_changed()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble("/dialogs/gridtiler/YPad", YPadding.getValue("px"));
+}
+
+
+/**
+ * checked/unchecked autosize Rows button.
+ */
+void GridArrangeTab::on_RowSize_checkbutton_changed()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (RowHeightButton.get_active()) {
+ prefs->setDouble("/dialogs/gridtiler/AutoRowSize", 20);
+ } else {
+ prefs->setDouble("/dialogs/gridtiler/AutoRowSize", -20);
+ }
+ RowHeightBox.set_sensitive ( !RowHeightButton.get_active());
+}
+
+/**
+ * checked/unchecked autosize Rows button.
+ */
+void GridArrangeTab::on_ColSize_checkbutton_changed()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (ColumnWidthButton.get_active()) {
+ prefs->setDouble("/dialogs/gridtiler/AutoColSize", 20);
+ } else {
+ prefs->setDouble("/dialogs/gridtiler/AutoColSize", -20);
+ }
+ ColumnWidthBox.set_sensitive ( !ColumnWidthButton.get_active());
+}
+
+/**
+ * changed value in columns spinbox.
+ */
+void GridArrangeTab::on_rowSize_spinbutton_changed()
+{
+ // quit if run by the attr_changed listener
+ if (updating) {
+ return;
+ }
+
+ // in turn, prevent listener from responding
+ updating = true;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble("/dialogs/gridtiler/RowHeight", RowHeightSpinner.get_value());
+ updating=false;
+
+}
+
+/**
+ * changed value in rows spinbox.
+ */
+void GridArrangeTab::on_colSize_spinbutton_changed()
+{
+ // quit if run by the attr_changed listener
+ if (updating) {
+ return;
+ }
+
+ // in turn, prevent listener from responding
+ updating = true;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble("/dialogs/gridtiler/ColWidth", ColumnWidthSpinner.get_value());
+ updating=false;
+
+}
+
+/**
+ * changed Radio button in Spacing group.
+ */
+void GridArrangeTab::Spacing_button_changed()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (SpaceManualRadioButton.get_active()) {
+ prefs->setDouble("/dialogs/gridtiler/SpacingType", 20);
+ } else {
+ prefs->setDouble("/dialogs/gridtiler/SpacingType", -20);
+ }
+
+ XPadding.set_sensitive ( SpaceManualRadioButton.get_active());
+ YPadding.set_sensitive ( SpaceManualRadioButton.get_active());
+}
+
+/**
+ * changed Anchor selection widget.
+ */
+void GridArrangeTab::Align_changed()
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ VertAlign = AlignmentSelector.getVerticalAlignment();
+ prefs->setInt("/dialogs/gridtiler/VertAlign", VertAlign);
+ HorizAlign = AlignmentSelector.getHorizontalAlignment();
+ prefs->setInt("/dialogs/gridtiler/HorizAlign", HorizAlign);
+}
+
+/**
+ * Desktop selection changed
+ */
+void GridArrangeTab::updateSelection()
+{
+ // quit if run by the attr_changed listener
+ if (updating) {
+ return;
+ }
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ // in turn, prevent listener from responding
+ updating = true;
+ SPDesktop *desktop = Parent->getDesktop();
+ Inkscape::Selection *selection = desktop ? desktop->selection : 0;
+ GSList const *items = selection ? selection->itemList() : 0;
+
+ if (items) {
+ int selcount = g_slist_length((GSList *)items);
+
+ if (NoOfColsSpinner.get_value() > 1 && NoOfRowsSpinner.get_value() > 1){
+ // Update the number of rows assuming number of columns wanted remains same.
+ double NoOfRows = ceil(selcount / NoOfColsSpinner.get_value());
+ NoOfRowsSpinner.set_value(NoOfRows);
+
+ // if the selection has less than the number set for one row, reduce it appropriately
+ if (selcount < NoOfColsSpinner.get_value()) {
+ double NoOfCols = ceil(selcount / NoOfRowsSpinner.get_value());
+ NoOfColsSpinner.set_value(NoOfCols);
+ prefs->setInt("/dialogs/gridtiler/NoOfCols", NoOfCols);
+ }
+ } else {
+ double PerRow = ceil(sqrt(selcount));
+ double PerCol = ceil(sqrt(selcount));
+ NoOfRowsSpinner.set_value(PerRow);
+ NoOfColsSpinner.set_value(PerCol);
+ prefs->setInt("/dialogs/gridtiler/NoOfCols", static_cast<int>(PerCol));
+ }
+ }
+
+ updating = false;
+}
+
+
+
+/*##########################
+## Experimental
+##########################*/
+
+static void updateSelectionCallback(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, GridArrangeTab *dlg)
+{
+ dlg->updateSelection();
+}
+
+
+//#########################################################################
+//## C O N S T R U C T O R / D E S T R U C T O R
+//#########################################################################
+/**
+ * Constructor
+ */
+GridArrangeTab::GridArrangeTab(ArrangeDialog *parent)
+ : Parent(parent),
+ XPadding(_("X:"), _("Horizontal spacing between columns."), UNIT_TYPE_LINEAR, "", "object-columns", &PaddingUnitMenu),
+ YPadding(_("Y:"), _("Vertical spacing between rows."), XPadding, "", "object-rows", &PaddingUnitMenu),
+#if WITH_GTKMM_3_0
+ PaddingTable(Gtk::manage(new Gtk::Grid()))
+#else
+ PaddingTable(Gtk::manage(new Gtk::Table(2, 2, false)))
+#endif
+{
+ // bool used by spin button callbacks to stop loops where they change each other.
+ updating = false;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ // could not do this in gtkmm - there's no Gtk::SizeGroup public constructor (!)
+ GtkSizeGroup *_col1 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+ GtkSizeGroup *_col2 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+ GtkSizeGroup *_col3 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
+
+ {
+ // Selection Change signal
+ g_signal_connect ( G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (updateSelectionCallback), this);
+ }
+
+ Gtk::Box *contents = this;
+
+#define MARGIN 2
+
+ //##Set up the panel
+
+ SPDesktop *desktop = Parent->getDesktop();
+
+ Inkscape::Selection *selection = desktop ? desktop->selection : 0;
+ g_return_if_fail( selection );
+ int selcount = 1;
+ if (!selection->isEmpty()) {
+ GSList const *items = selection->itemList();
+ selcount = g_slist_length((GSList *)items);
+ }
+
+
+ /*#### Number of Rows ####*/
+
+ double PerRow = ceil(sqrt(selcount));
+ double PerCol = ceil(sqrt(selcount));
+
+ #ifdef DEBUG_GRID_ARRANGE
+ g_print("/n PerRox = %f PerCol = %f selcount = %d",PerRow,PerCol,selcount);
+ #endif
+
+ NoOfRowsLabel.set_text_with_mnemonic(_("_Rows:"));
+ NoOfRowsLabel.set_mnemonic_widget(NoOfRowsSpinner);
+ NoOfRowsBox.pack_start(NoOfRowsLabel, false, false, MARGIN);
+
+ NoOfRowsSpinner.set_digits(0);
+ NoOfRowsSpinner.set_increments(1, 0);
+ NoOfRowsSpinner.set_range(1.0, 10000.0);
+ NoOfRowsSpinner.set_value(PerCol);
+ NoOfRowsSpinner.signal_changed().connect(sigc::mem_fun(*this, &GridArrangeTab::on_col_spinbutton_changed));
+ NoOfRowsSpinner.set_tooltip_text(_("Number of rows"));
+ NoOfRowsBox.pack_start(NoOfRowsSpinner, false, false, MARGIN);
+ gtk_size_group_add_widget(_col1, (GtkWidget *) NoOfRowsBox.gobj());
+
+ RowHeightButton.set_label(_("Equal _height"));
+ RowHeightButton.set_use_underline(true);
+ double AutoRow = prefs->getDouble("/dialogs/gridtiler/AutoRowSize", 15);
+ if (AutoRow>0)
+ AutoRowSize=true;
+ else
+ AutoRowSize=false;
+ RowHeightButton.set_active(AutoRowSize);
+
+ NoOfRowsBox.pack_start(RowHeightButton, false, false, MARGIN);
+
+ RowHeightButton.set_tooltip_text(_("If not set, each row has the height of the tallest object in it"));
+ RowHeightButton.signal_toggled().connect(sigc::mem_fun(*this, &GridArrangeTab::on_RowSize_checkbutton_changed));
+
+ SpinsHBox.pack_start(NoOfRowsBox, false, false, MARGIN);
+
+
+ /*#### Label for X ####*/
+ padXByYLabel.set_label(" ");
+ XByYLabelVBox.pack_start(padXByYLabel, false, false, MARGIN);
+ XByYLabel.set_markup(" &#215; ");
+ XByYLabelVBox.pack_start(XByYLabel, false, false, MARGIN);
+ SpinsHBox.pack_start(XByYLabelVBox, false, false, MARGIN);
+ gtk_size_group_add_widget(_col2, GTK_WIDGET(XByYLabelVBox.gobj()));
+
+ /*#### Number of columns ####*/
+
+ NoOfColsLabel.set_text_with_mnemonic(_("_Columns:"));
+ NoOfColsLabel.set_mnemonic_widget(NoOfColsSpinner);
+ NoOfColsBox.pack_start(NoOfColsLabel, false, false, MARGIN);
+
+ NoOfColsSpinner.set_digits(0);
+ NoOfColsSpinner.set_increments(1, 0);
+ NoOfColsSpinner.set_range(1.0, 10000.0);
+ NoOfColsSpinner.set_value(PerRow);
+ NoOfColsSpinner.signal_changed().connect(sigc::mem_fun(*this, &GridArrangeTab::on_row_spinbutton_changed));
+ NoOfColsSpinner.set_tooltip_text(_("Number of columns"));
+ NoOfColsBox.pack_start(NoOfColsSpinner, false, false, MARGIN);
+ gtk_size_group_add_widget(_col3, GTK_WIDGET(NoOfColsBox.gobj()));
+
+ ColumnWidthButton.set_label(_("Equal _width"));
+ ColumnWidthButton.set_use_underline(true);
+ double AutoCol = prefs->getDouble("/dialogs/gridtiler/AutoColSize", 15);
+ if (AutoCol>0)
+ AutoColSize=true;
+ else
+ AutoColSize=false;
+ ColumnWidthButton.set_active(AutoColSize);
+ NoOfColsBox.pack_start(ColumnWidthButton, false, false, MARGIN);
+
+ ColumnWidthButton.set_tooltip_text(_("If not set, each column has the width of the widest object in it"));
+ ColumnWidthButton.signal_toggled().connect(sigc::mem_fun(*this, &GridArrangeTab::on_ColSize_checkbutton_changed));
+
+ SpinsHBox.pack_start(NoOfColsBox, false, false, MARGIN);
+
+ TileBox.pack_start(SpinsHBox, false, false, MARGIN);
+
+ VertAlign = prefs->getInt("/dialogs/gridtiler/VertAlign", 1);
+ HorizAlign = prefs->getInt("/dialogs/gridtiler/HorizAlign", 1);
+
+ // Anchor selection widget
+ AlignLabel.set_label("Alignment:");
+ AlignLabel.set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
+ AlignmentSelector.setAlignment(HorizAlign, VertAlign);
+ AlignmentSelector.on_selectionChanged().connect(sigc::mem_fun(*this, &GridArrangeTab::Align_changed));
+ TileBox.pack_start(AlignLabel, false, false, MARGIN);
+ TileBox.pack_start(AlignmentSelector, true, false, MARGIN);
+
+ {
+ /*#### Radio buttons to control spacing manually or to fit selection bbox ####*/
+ SpaceByBBoxRadioButton.set_label(_("_Fit into selection box"));
+ SpaceByBBoxRadioButton.set_use_underline (true);
+ SpaceByBBoxRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &GridArrangeTab::Spacing_button_changed));
+ SpacingGroup = SpaceByBBoxRadioButton.get_group();
+
+ SpacingVBox.pack_start(SpaceByBBoxRadioButton, false, false, MARGIN);
+
+ SpaceManualRadioButton.set_label(_("_Set spacing:"));
+ SpaceManualRadioButton.set_use_underline (true);
+ SpaceManualRadioButton.set_group(SpacingGroup);
+ SpaceManualRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &GridArrangeTab::Spacing_button_changed));
+ SpacingVBox.pack_start(SpaceManualRadioButton, false, false, MARGIN);
+
+ TileBox.pack_start(SpacingVBox, false, false, MARGIN);
+ }
+
+ {
+ /*#### Padding ####*/
+ PaddingUnitMenu.setUnitType(UNIT_TYPE_LINEAR);
+ PaddingUnitMenu.setUnit("px");
+
+ YPadding.setDigits(5);
+ YPadding.setIncrements(0.2, 0);
+ YPadding.setRange(-10000, 10000);
+ double yPad = prefs->getDouble("/dialogs/gridtiler/YPad", 15);
+ YPadding.setValue(yPad, "px");
+ YPadding.signal_value_changed().connect(sigc::mem_fun(*this, &GridArrangeTab::on_ypad_spinbutton_changed));
+
+ XPadding.setDigits(5);
+ XPadding.setIncrements(0.2, 0);
+ XPadding.setRange(-10000, 10000);
+ double xPad = prefs->getDouble("/dialogs/gridtiler/XPad", 15);
+ XPadding.setValue(xPad, "px");
+
+ XPadding.signal_value_changed().connect(sigc::mem_fun(*this, &GridArrangeTab::on_xpad_spinbutton_changed));
+ }
+
+ PaddingTable->set_border_width(MARGIN);
+
+#if WITH_GTKMM_3_0
+ PaddingTable->set_row_spacing(MARGIN);
+ PaddingTable->set_column_spacing(MARGIN);
+ PaddingTable->attach(XPadding, 0, 0, 1, 1);
+ PaddingTable->attach(PaddingUnitMenu, 1, 0, 1, 1);
+ PaddingTable->attach(YPadding, 0, 1, 1, 1);
+#else
+ PaddingTable->set_row_spacings(MARGIN);
+ PaddingTable->set_col_spacings(MARGIN);
+ PaddingTable->attach(XPadding, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+ PaddingTable->attach(PaddingUnitMenu, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
+ PaddingTable->attach(YPadding, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
+#endif
+
+ TileBox.pack_start(*PaddingTable, false, false, MARGIN);
+
+ contents->pack_start(TileBox);
+
+ double SpacingType = prefs->getDouble("/dialogs/gridtiler/SpacingType", 15);
+ if (SpacingType>0) {
+ ManualSpacing=true;
+ } else {
+ ManualSpacing=false;
+ }
+ SpaceManualRadioButton.set_active(ManualSpacing);
+ SpaceByBBoxRadioButton.set_active(!ManualSpacing);
+ XPadding.set_sensitive (ManualSpacing);
+ YPadding.set_sensitive (ManualSpacing);
+
+ //## The OK button FIXME
+ /*TileOkButton = addResponseButton(C_("Rows and columns dialog","_Arrange"), GTK_RESPONSE_APPLY);
+ TileOkButton->set_use_underline(true);
+ TileOkButton->set_tooltip_text(_("Arrange selected objects"));*/
+
+ show_all_children();
+}
+
+} //namespace Dialog
+} //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:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/grid-arrange-tab.h b/src/ui/dialog/grid-arrange-tab.h
new file mode 100644
index 000000000..9d6700b39
--- /dev/null
+++ b/src/ui/dialog/grid-arrange-tab.h
@@ -0,0 +1,154 @@
+/**
+ * @brief Arranges Objects into a Grid
+ */
+/* Authors:
+ * Bob Jamison ( based off trace dialog)
+ * John Cliff
+ * Other dudes from The Inkscape Organization
+ * Abhishek Sharma
+ * Declara Denis
+ *
+ * Copyright (C) 2004 Bob Jamison
+ * Copyright (C) 2004 John Cliff
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_GRID_ARRANGE_TAB_H
+#define INKSCAPE_UI_DIALOG_GRID_ARRANGE_TAB_H
+
+#include <gtkmm.h>
+
+#include "ui/dialog/arrange-tab.h"
+
+#include "ui/widget/anchor-selector.h"
+#include "ui/widget/scalar-unit.h"
+#include "ui/widget/spinbutton.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class ArrangeDialog;
+
+/**
+ * Dialog for tiling an object
+ */
+class GridArrangeTab : public ArrangeTab {
+public:
+ GridArrangeTab(ArrangeDialog *parent);
+ virtual ~GridArrangeTab() {};
+
+ /**
+ * Do the actual work
+ */
+ virtual void arrange();
+
+ /**
+ * Respond to selection change
+ */
+ void updateSelection();
+
+ // Callbacks from spinbuttons
+ void on_row_spinbutton_changed();
+ void on_col_spinbutton_changed();
+ void on_xpad_spinbutton_changed();
+ void on_ypad_spinbutton_changed();
+ void on_RowSize_checkbutton_changed();
+ void on_ColSize_checkbutton_changed();
+ void on_rowSize_spinbutton_changed();
+ void on_colSize_spinbutton_changed();
+ void Spacing_button_changed();
+ void Align_changed();
+
+
+private:
+ GridArrangeTab(GridArrangeTab const &d); // no copy
+ void operator=(GridArrangeTab const &d); // no assign
+
+ ArrangeDialog *Parent;
+
+ bool userHidden;
+ bool updating;
+
+ Gtk::VBox TileBox;
+ Gtk::Button *TileOkButton;
+ Gtk::Button *TileCancelButton;
+
+ // Number selected label
+ Gtk::Label SelectionContentsLabel;
+
+
+ Gtk::HBox AlignHBox;
+ Gtk::HBox SpinsHBox;
+
+ // Number per Row
+ Gtk::VBox NoOfColsBox;
+ Gtk::Label NoOfColsLabel;
+ Inkscape::UI::Widget::SpinButton NoOfColsSpinner;
+ bool AutoRowSize;
+ Gtk::CheckButton RowHeightButton;
+
+ Gtk::VBox XByYLabelVBox;
+ Gtk::Label padXByYLabel;
+ Gtk::Label XByYLabel;
+
+ // Number per Column
+ Gtk::VBox NoOfRowsBox;
+ Gtk::Label NoOfRowsLabel;
+ Inkscape::UI::Widget::SpinButton NoOfRowsSpinner;
+ bool AutoColSize;
+ Gtk::CheckButton ColumnWidthButton;
+
+ // Alignment
+ Gtk::Label AlignLabel;
+ Inkscape::UI::Widget::AnchorSelector AlignmentSelector;
+ double VertAlign;
+ double HorizAlign;
+
+ Inkscape::UI::Widget::UnitMenu PaddingUnitMenu;
+ Inkscape::UI::Widget::ScalarUnit XPadding;
+ Inkscape::UI::Widget::ScalarUnit YPadding;
+
+#if WITH_GTKMM_3_0
+ Gtk::Grid *PaddingTable;
+#else
+ Gtk::Table *PaddingTable;
+#endif
+
+ // BBox or manual spacing
+ Gtk::VBox SpacingVBox;
+ Gtk::RadioButtonGroup SpacingGroup;
+ Gtk::RadioButton SpaceByBBoxRadioButton;
+ Gtk::RadioButton SpaceManualRadioButton;
+ bool ManualSpacing;
+
+ // Row height
+ Gtk::VBox RowHeightVBox;
+ Gtk::HBox RowHeightBox;
+ Gtk::Label RowHeightLabel;
+ Inkscape::UI::Widget::SpinButton RowHeightSpinner;
+
+ // Column width
+ Gtk::VBox ColumnWidthVBox;
+ Gtk::HBox ColumnWidthBox;
+ Gtk::Label ColumnWidthLabel;
+ Inkscape::UI::Widget::SpinButton ColumnWidthSpinner;
+};
+
+} //namespace Dialog
+} //namespace UI
+} //namespace Inkscape
+
+#endif /* INKSCAPE_UI_DIALOG_GRID_ARRANGE_TAB_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:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/polar-arrange-tab.cpp b/src/ui/dialog/polar-arrange-tab.cpp
new file mode 100644
index 000000000..a00b8fc02
--- /dev/null
+++ b/src/ui/dialog/polar-arrange-tab.cpp
@@ -0,0 +1,414 @@
+/**
+ * @brief Arranges Objects into a Circle/Ellipse
+ */
+/* Authors:
+ * Declara Denis
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/dialog/polar-arrange-tab.h"
+#include "ui/dialog/tile.h"
+
+#include <2geom/transforms.h>
+#include <glibmm/i18n.h>
+
+#include "verbs.h"
+#include "preferences.h"
+#include "inkscape.h"
+#include "desktop-handles.h"
+#include "selection.h"
+#include "document.h"
+#include "document-undo.h"
+#include "sp-item.h"
+#include "widgets/icon.h"
+#include "desktop.h"
+#include "sp-ellipse.h"
+#include "sp-item-transform.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_)
+ : parent(parent_),
+ parametersTable(3, 3, false),
+ centerY("", "Y coordinate of the center", UNIT_TYPE_LINEAR),
+ centerX("", "X coordinate of the center", centerY),
+ radiusY("", "Y coordinate of the radius", UNIT_TYPE_LINEAR),
+ radiusX("", "X coordinate of the radius", radiusY),
+ angleY("", "Starting angle", UNIT_TYPE_RADIAL),
+ angleX("", "End angle", angleY)
+{
+ anchorPointLabel.set_text(C_("Polar arrange tab", "Anchor point:"));
+ anchorPointLabel.set_alignment(Gtk::ALIGN_START);
+ pack_start(anchorPointLabel, false, false);
+
+ anchorBoundingBoxRadio.set_label(C_("Polar arrange tab", "Object's bounding box:"));
+ anchorRadioGroup = anchorBoundingBoxRadio.get_group();
+ anchorBoundingBoxRadio.signal_toggled().connect(sigc::mem_fun(*this, &PolarArrangeTab::on_anchor_radio_changed));
+ pack_start(anchorBoundingBoxRadio, false, false);
+
+ pack_start(anchorSelector, false, false);
+
+ anchorObjectPivotRadio.set_label(C_("Polar arrange tab", "Object's rotational center"));
+ anchorObjectPivotRadio.set_group(anchorRadioGroup);
+ anchorObjectPivotRadio.signal_toggled().connect(sigc::mem_fun(*this, &PolarArrangeTab::on_anchor_radio_changed));
+ pack_start(anchorObjectPivotRadio, false, false);
+
+ arrangeOnLabel.set_text(C_("Polar arrange tab", "Arrange on:"));
+ arrangeOnLabel.set_alignment(Gtk::ALIGN_START);
+ pack_start(arrangeOnLabel, false, false);
+
+ arrangeOnFirstCircleRadio.set_label(C_("Polar arrange tab", "First selected circle/ellipse/arc"));
+ arrangeRadioGroup = arrangeOnFirstCircleRadio.get_group();
+ arrangeOnFirstCircleRadio.signal_toggled().connect(sigc::mem_fun(*this, &PolarArrangeTab::on_arrange_radio_changed));
+ pack_start(arrangeOnFirstCircleRadio, false, false);
+
+ arrangeOnLastCircleRadio.set_label(C_("Polar arrange tab", "Last selected circle/ellipse/arc"));
+ arrangeOnLastCircleRadio.set_group(arrangeRadioGroup);
+ arrangeOnLastCircleRadio.signal_toggled().connect(sigc::mem_fun(*this, &PolarArrangeTab::on_arrange_radio_changed));
+ pack_start(arrangeOnLastCircleRadio, false, false);
+
+ arrangeOnParametersRadio.set_label(C_("Polar arrange tab", "Parameterized:"));
+ arrangeOnParametersRadio.set_group(arrangeRadioGroup);
+ arrangeOnParametersRadio.signal_toggled().connect(sigc::mem_fun(*this, &PolarArrangeTab::on_arrange_radio_changed));
+ pack_start(arrangeOnParametersRadio, false, false);
+
+ centerLabel.set_text(_("Center X/Y:"));
+ parametersTable.attach(centerLabel, 0, 1, 0, 1, Gtk::FILL);
+ centerX.setDigits(2);
+ centerX.setIncrements(0.2, 0);
+ centerX.setRange(-10000, 10000);
+ centerX.setValue(0, "px");
+ centerY.setDigits(2);
+ centerY.setIncrements(0.2, 0);
+ centerY.setRange(-10000, 10000);
+ centerY.setValue(0, "px");
+ parametersTable.attach(centerX, 1, 2, 0, 1, Gtk::FILL);
+ parametersTable.attach(centerY, 2, 3, 0, 1, Gtk::FILL);
+
+ radiusLabel.set_text(_("Radius X/Y:"));
+ parametersTable.attach(radiusLabel, 0, 1, 1, 2, Gtk::FILL);
+ radiusX.setDigits(2);
+ radiusX.setIncrements(0.2, 0);
+ radiusX.setRange(0.001, 10000);
+ radiusX.setValue(100, "px");
+ radiusY.setDigits(2);
+ radiusY.setIncrements(0.2, 0);
+ radiusY.setRange(0.001, 10000);
+ radiusY.setValue(100, "px");
+ parametersTable.attach(radiusX, 1, 2, 1, 2, Gtk::FILL);
+ parametersTable.attach(radiusY, 2, 3, 1, 2, Gtk::FILL);
+
+ angleLabel.set_text(_("Angle X/Y:"));
+ parametersTable.attach(angleLabel, 0, 1, 2, 3, Gtk::FILL);
+ angleX.setDigits(2);
+ angleX.setIncrements(0.2, 0);
+ angleX.setRange(-10000, 10000);
+ angleX.setValue(0, "°");
+ angleY.setDigits(2);
+ angleY.setIncrements(0.2, 0);
+ angleY.setRange(-10000, 10000);
+ angleY.setValue(180, "°");
+ parametersTable.attach(angleX, 1, 2, 2, 3, Gtk::FILL);
+ parametersTable.attach(angleY, 2, 3, 2, 3, Gtk::FILL);
+ pack_start(parametersTable, false, false);
+
+ rotateObjectsCheckBox.set_label(_("Rotate objects"));
+ rotateObjectsCheckBox.set_active(true);
+ pack_start(rotateObjectsCheckBox, false, false);
+
+ centerX.set_sensitive(false);
+ centerY.set_sensitive(false);
+ angleX.set_sensitive(false);
+ angleY.set_sensitive(false);
+ radiusX.set_sensitive(false);
+ radiusY.set_sensitive(false);
+}
+
+/**
+ * This function rotates an item around a given point by a given amount
+ * @param item item to rotate
+ * @param center center of the rotation to perform
+ * @param rotation amount to rotate the object by
+ */
+static void rotateAround(SPItem *item, Geom::Point center, Geom::Rotate const &rotation)
+{
+ Geom::Translate const s(center);
+ Geom::Affine affine = Geom::Affine(s).inverse() * Geom::Affine(rotation) * Geom::Affine(s);
+
+ // Save old center
+ center = item->getCenter();
+
+ item->set_i2d_affine(item->i2dt_affine() * affine);
+ item->doWriteTransform(item->getRepr(), item->transform);
+
+ if(item->isCenterSet())
+ {
+ item->setCenter(center * affine);
+ item->updateRepr();
+ }
+}
+
+/**
+ * Calculates the angle at which to put an object given the total amount
+ * of objects, the index of the objects as well as the arc start and end
+ * points
+ * @param arcBegin angle at which the arc begins
+ * @param arcEnd angle at which the arc ends
+ * @param count number of objects in the selection
+ * @param n index of the object in the selection
+ */
+static float calcAngle(float arcBegin, float arcEnd, int count, int n)
+{
+ float arcLength = arcEnd - arcBegin;
+ float delta = std::abs(std::abs(arcLength) - 2*M_PI);
+ if(delta > 0.01) count--; // If not a complete circle, put an object also at the extremes of the arc;
+
+ float angle = n / (float)count;
+ // Normalize for arcLength:
+ angle = angle * arcLength;
+ angle += arcBegin;
+
+ return angle;
+}
+
+/**
+ * Calculates the point at which an object needs to be, given the center of the ellipse,
+ * it's radius (x and y), as well as the angle
+ */
+static Geom::Point calcPoint(float cx, float cy, float rx, float ry, float angle)
+{
+ return Geom::Point(cx + cos(angle) * rx, cy + sin(angle) * ry);
+}
+
+/**
+ * Returns the selected anchor point in document coordinates. If anchor
+ * is 0 to 8, then a bounding box point has been choosen. If it is 9 however
+ * the rotational center is chosen.
+ * @todo still using a hack to get the real coordinate space (subtracting document height
+ * and inverting axes)
+ */
+static Geom::Point getAnchorPoint(int anchor, SPItem *item)
+{
+ Geom::Point source;
+
+ Geom::OptRect bbox = item->documentVisualBounds();
+
+ switch(anchor)
+ {
+ case 0: // Top - Left
+ case 3: // Middle - Left
+ case 6: // Bottom - Left
+ source[0] = bbox->min()[Geom::X];
+ break;
+ case 1: // Top - Middle
+ case 4: // Middle - Middle
+ case 7: // Bottom - Middle
+ source[0] = (bbox->min()[Geom::X] + bbox->max()[Geom::X]) / 2.0f;
+ break;
+ case 2: // Top - Right
+ case 5: // Middle - Right
+ case 8: // Bottom - Right
+ source[0] = bbox->max()[Geom::X];
+ break;
+ };
+
+ switch(anchor)
+ {
+ case 0: // Top - Left
+ case 1: // Top - Middle
+ case 2: // Top - Right
+ source[1] = bbox->min()[Geom::Y];
+ break;
+ case 3: // Middle - Left
+ case 4: // Middle - Middle
+ case 5: // Middle - Right
+ source[1] = (bbox->min()[Geom::Y] + bbox->max()[Geom::Y]) / 2.0f;
+ break;
+ case 6: // Bottom - Left
+ case 7: // Bottom - Middle
+ case 8: // Bottom - Right
+ source[1] = bbox->max()[Geom::Y];
+ break;
+ };
+
+ // If using center
+ if(anchor == 9)
+ source = item->getCenter();
+ else
+ {
+ // FIXME:
+ source[1] -= item->document->getHeight().value("px");
+ source[1] *= -1;
+ }
+
+ return source;
+}
+
+/**
+ * Moves an SPItem to a given location, the location is based on the given anchor point.
+ * @param anchor 0 to 8 are the various bounding box points like follows:
+ * 0 1 2
+ * 3 4 5
+ * 6 7 8
+ * Anchor mode 9 is the rotational center of the object
+ * @param item Item to move
+ * @param p point at which to move the object
+ */
+static void moveToPoint(int anchor, SPItem *item, Geom::Point p)
+{
+ sp_item_move_rel(item, Geom::Translate(p - getAnchorPoint(anchor, item)));
+}
+
+void PolarArrangeTab::arrange()
+{
+ Inkscape::Selection *selection = sp_desktop_selection(parent->getDesktop());
+ const GSList *items, *tmp;
+ tmp = items = selection->itemList();
+ SPGenericEllipse *referenceEllipse = NULL; // Last ellipse in selection
+
+ bool arrangeOnEllipse = !arrangeOnParametersRadio.get_active();
+ bool arrangeOnFirstEllipse = arrangeOnEllipse && arrangeOnFirstCircleRadio.get_active();
+
+ int count = 0;
+ while(tmp)
+ {
+ if(arrangeOnEllipse)
+ {
+ SPItem *item = SP_ITEM(tmp->data);
+
+ if(arrangeOnFirstEllipse)
+ {
+ // The first selected ellipse is actually the last one in the list
+ if(SP_IS_GENERICELLIPSE(item))
+ referenceEllipse = SP_GENERICELLIPSE(item);
+ } else {
+ // The last selected ellipse is actually the first in list
+ if(SP_IS_GENERICELLIPSE(item) && referenceEllipse == NULL)
+ referenceEllipse = SP_GENERICELLIPSE(item);
+ }
+ }
+ tmp = tmp->next;
+ ++count;
+ }
+
+ float cx, cy; // Center of the ellipse
+ float rx, ry; // Radiuses of the ellipse in x and y direction
+ float arcBeg, arcEnd; // begin and end angles for arcs
+ Geom::Affine transformation; // Any additional transformation to apply to the objects
+
+ if(arrangeOnEllipse)
+ {
+ if(referenceEllipse == NULL)
+ {
+ Gtk::MessageDialog dialog(_("Couldn't find an ellipse in selection"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_CLOSE, true);
+ dialog.run();
+ return;
+ } else {
+ cx = referenceEllipse->cx.value;
+ cy = referenceEllipse->cy.value;
+ rx = referenceEllipse->rx.value;
+ ry = referenceEllipse->ry.value;
+ arcBeg = referenceEllipse->start;
+ arcEnd = referenceEllipse->end;
+
+ transformation = referenceEllipse->i2dt_affine();
+
+ // We decrement the count by 1 as we are not going to lay
+ // out the reference ellipse
+ --count;
+ }
+
+ } else {
+ // Read options from UI
+ cx = centerX.getValue("px");
+ cy = centerY.getValue("px");
+ rx = radiusX.getValue("px");
+ ry = radiusY.getValue("px");
+ arcBeg = angleX.getValue("rad");
+ arcEnd = angleY.getValue("rad");
+ transformation.setIdentity();
+ referenceEllipse = NULL;
+ }
+
+ int anchor = 9;
+ if(anchorBoundingBoxRadio.get_active())
+ {
+ anchor = anchorSelector.getHorizontalAlignment() +
+ anchorSelector.getVerticalAlignment() * 3;
+ }
+
+ Geom::Point realCenter = Geom::Point(cx, cy) * transformation;
+
+ tmp = items;
+ int i = 0;
+ while(tmp)
+ {
+ SPItem *item = SP_ITEM(tmp->data);
+
+ // Ignore the reference ellipse if any
+ if(item != referenceEllipse)
+ {
+ float angle = calcAngle(arcBeg, arcEnd, count, i);
+ Geom::Point newLocation = calcPoint(cx, cy, rx, ry, angle) * transformation;
+
+ moveToPoint(anchor, item, newLocation);
+
+ if(rotateObjectsCheckBox.get_active()) {
+ // Calculate the angle by which to rotate each object
+ angle = -atan2f(newLocation.x() - realCenter.x(), newLocation.y() - realCenter.y());
+ rotateAround(item, newLocation, Geom::Rotate(angle));
+ }
+
+ ++i;
+ }
+ tmp = tmp->next;
+ }
+
+ DocumentUndo::done(sp_desktop_document(parent->getDesktop()), SP_VERB_SELECTION_ARRANGE,
+ _("Arrange on ellipse"));
+}
+
+void PolarArrangeTab::updateSelection()
+{
+}
+
+void PolarArrangeTab::on_arrange_radio_changed()
+{
+ bool arrangeParametric = arrangeOnParametersRadio.get_active();
+
+ centerX.set_sensitive(arrangeParametric);
+ centerY.set_sensitive(arrangeParametric);
+
+ angleX.set_sensitive(arrangeParametric);
+ angleY.set_sensitive(arrangeParametric);
+
+ radiusX.set_sensitive(arrangeParametric);
+ radiusY.set_sensitive(arrangeParametric);
+
+ parametersTable.set_visible(arrangeParametric);
+}
+
+void PolarArrangeTab::on_anchor_radio_changed()
+{
+ bool anchorBoundingBox = anchorBoundingBoxRadio.get_active();
+
+ anchorSelector.set_sensitive(anchorBoundingBox);
+}
+
+} //namespace Dialog
+} //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:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/polar-arrange-tab.h b/src/ui/dialog/polar-arrange-tab.h
new file mode 100644
index 000000000..bfed40bbd
--- /dev/null
+++ b/src/ui/dialog/polar-arrange-tab.h
@@ -0,0 +1,100 @@
+/**
+ * @brief Arranges Objects into a Circle/Ellipse
+ */
+/* Authors:
+ * Declara Denis
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_UI_DIALOG_POLAR_ARRANGE_TAB_H
+#define INKSCAPE_UI_DIALOG_POLAR_ARRANGE_TAB_H
+
+#include "ui/dialog/arrange-tab.h"
+
+#include "ui/widget/anchor-selector.h"
+#include "ui/widget/scalar-unit.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialog {
+
+class ArrangeDialog;
+
+/**
+ * PolarArrangeTab is a Tab displayed in the Arrange dialog and contains
+ * enables the user to arrange objects on a circular or elliptical shape
+ */
+class PolarArrangeTab : public ArrangeTab {
+public:
+ PolarArrangeTab(ArrangeDialog *parent_);
+ virtual ~PolarArrangeTab() {};
+
+ /**
+ * Do the actual arrangement
+ */
+ virtual void arrange();
+
+ /**
+ * Respond to selection change
+ */
+ void updateSelection();
+
+ void on_anchor_radio_changed();
+ void on_arrange_radio_changed();
+
+private:
+ PolarArrangeTab(PolarArrangeTab const &d); // no copy
+ void operator=(PolarArrangeTab const &d); // no assign
+
+ ArrangeDialog *parent;
+
+ Gtk::Label anchorPointLabel;
+
+ Gtk::RadioButtonGroup anchorRadioGroup;
+ Gtk::RadioButton anchorBoundingBoxRadio;
+ Gtk::RadioButton anchorObjectPivotRadio;
+ Inkscape::UI::Widget::AnchorSelector anchorSelector;
+
+ Gtk::Label arrangeOnLabel;
+
+ Gtk::RadioButtonGroup arrangeRadioGroup;
+ Gtk::RadioButton arrangeOnFirstCircleRadio;
+ Gtk::RadioButton arrangeOnLastCircleRadio;
+ Gtk::RadioButton arrangeOnParametersRadio;
+
+ Gtk::Table parametersTable;
+
+ Gtk::Label centerLabel;
+ Inkscape::UI::Widget::ScalarUnit centerY;
+ Inkscape::UI::Widget::ScalarUnit centerX;
+
+ Gtk::Label radiusLabel;
+ Inkscape::UI::Widget::ScalarUnit radiusY;
+ Inkscape::UI::Widget::ScalarUnit radiusX;
+
+ Gtk::Label angleLabel;
+ Inkscape::UI::Widget::ScalarUnit angleY;
+ Inkscape::UI::Widget::ScalarUnit angleX;
+
+ Gtk::CheckButton rotateObjectsCheckBox;
+
+
+};
+
+} //namespace Dialog
+} //namespace UI
+} //namespace Inkscape
+
+#endif /* INKSCAPE_UI_DIALOG_POLAR_ARRANGE_TAB_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:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp
index c35d3b554..a3cffb3d4 100644
--- a/src/ui/dialog/tile.cpp
+++ b/src/ui/dialog/tile.cpp
@@ -6,878 +6,62 @@
* John Cliff
* Other dudes from The Inkscape Organization
* Abhishek Sharma
+ * Declara Denis
*
* Copyright (C) 2004 Bob Jamison
* Copyright (C) 2004 John Cliff
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-//#define DEBUG_GRID_ARRANGE 1
-#include "tile.h"
-#include <gtk/gtk.h> //for GTK_RESPONSE* types
-#include <glibmm/i18n.h>
-#include <gtkmm/stock.h>
+#include "ui/dialog/grid-arrange-tab.h"
+#include "ui/dialog/polar-arrange-tab.h"
-#if WITH_GTKMM_3_0
-# include <gtkmm/grid.h>
-#else
-# include <gtkmm/table.h>
-#endif
-
-#include <2geom/transforms.h>
+#include <glibmm/i18n.h>
+#include "tile.h"
#include "verbs.h"
-#include "preferences.h"
-#include "inkscape.h"
-#include "desktop-handles.h"
-#include "selection.h"
-#include "document.h"
-#include "document-undo.h"
-#include "sp-item.h"
-#include "widgets/icon.h"
-#include "desktop.h"
-
-/*
- * Sort items by their x co-ordinates, taking account of y (keeps rows intact)
- *
- * <0 *elem1 goes before *elem2
- * 0 *elem1 == *elem2
- * >0 *elem1 goes after *elem2
- */
-static int sp_compare_x_position(SPItem *first, SPItem *second)
-{
- using Geom::X;
- using Geom::Y;
-
- Geom::OptRect a = first->documentVisualBounds();
- Geom::OptRect b = second->documentVisualBounds();
-
- if ( !a || !b ) {
- // FIXME?
- return 0;
- }
-
- double const a_height = a->dimensions()[Y];
- double const b_height = b->dimensions()[Y];
-
- bool a_in_b_vert = false;
- if ((a->min()[Y] < b->min()[Y] + 0.1) && (a->min()[Y] > b->min()[Y] - b_height)) {
- a_in_b_vert = true;
- } else if ((b->min()[Y] < a->min()[Y] + 0.1) && (b->min()[Y] > a->min()[Y] - a_height)) {
- a_in_b_vert = true;
- } else if (b->min()[Y] == a->min()[Y]) {
- a_in_b_vert = true;
- } else {
- a_in_b_vert = false;
- }
-
- if (!a_in_b_vert) {
- return -1;
- }
- if (a_in_b_vert && a->min()[X] > b->min()[X]) {
- return 1;
- }
- if (a_in_b_vert && a->min()[X] < b->min()[X]) {
- return -1;
- }
- return 0;
-}
-
-/*
- * Sort items by their y co-ordinates.
- */
-static int
-sp_compare_y_position(SPItem *first, SPItem *second)
-{
- Geom::OptRect a = first->documentVisualBounds();
- Geom::OptRect b = second->documentVisualBounds();
-
- if ( !a || !b ) {
- // FIXME?
- return 0;
- }
-
- if (a->min()[Geom::Y] > b->min()[Geom::Y]) {
- return 1;
- }
- if (a->min()[Geom::Y] < b->min()[Geom::Y]) {
- return -1;
- }
-
- return 0;
-}
namespace Inkscape {
namespace UI {
namespace Dialog {
-
-//#########################################################################
-//## E V E N T S
-//#########################################################################
-
-/*
- *
- * This arranges the selection in a grid pattern.
- *
- */
-
-void TileDialog::Grid_Arrange ()
+ArrangeDialog::ArrangeDialog()
+ : UI::Widget::Panel("", "/dialogs/gridtiler", SP_VERB_SELECTION_ARRANGE),
+ _gridArrangeTab(new GridArrangeTab(this)),
+ _polarArrangeTab(new PolarArrangeTab(this))
{
+ Gtk::Box *contents = this->_getContents();
- int cnt,row_cnt,col_cnt,a,row,col;
- double grid_left,grid_top,col_width,row_height,paddingx,paddingy,width, height, new_x, new_y;
- double total_col_width,total_row_height;
- col_width = 0;
- row_height = 0;
- total_col_width=0;
- total_row_height=0;
-
- // check for correct numbers in the row- and col-spinners
- on_col_spinbutton_changed();
- on_row_spinbutton_changed();
-
- // set padding to manual values
- paddingx = XPadding.getValue("px");
- paddingy = YPadding.getValue("px");
-
- std::vector<double> row_heights;
- std::vector<double> col_widths;
- std::vector<double> row_ys;
- std::vector<double> col_xs;
-
- int NoOfCols = NoOfColsSpinner.get_value_as_int();
- int NoOfRows = NoOfRowsSpinner.get_value_as_int();
-
- width = 0;
- for (a=0;a<NoOfCols; a++){
- col_widths.push_back(width);
- }
-
- height = 0;
- for (a=0;a<NoOfRows; a++){
- row_heights.push_back(height);
- }
- grid_left = 99999;
- grid_top = 99999;
-
- SPDesktop *desktop = getDesktop();
- sp_desktop_document(desktop)->ensureUpToDate();
-
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
- const GSList *items = selection ? selection->itemList() : 0;
- cnt=0;
- for (; items != NULL; items = items->next) {
- SPItem *item = SP_ITEM(items->data);
- Geom::OptRect b = item->documentVisualBounds();
- if (!b) {
- continue;
- }
-
- width = b->dimensions()[Geom::X];
- height = b->dimensions()[Geom::Y];
-
- if (b->min()[Geom::X] < grid_left) {
- grid_left = b->min()[Geom::X];
- }
- if (b->min()[Geom::Y] < grid_top) {
- grid_top = b->min()[Geom::Y];
- }
- if (width > col_width) {
- col_width = width;
- }
- if (height > row_height) {
- row_height = height;
- }
- }
-
-
- // require the sorting done before we can calculate row heights etc.
-
- g_return_if_fail(selection);
- const GSList *items2 = selection->itemList();
- GSList *rev = g_slist_copy(const_cast<GSList *>(items2));
- GSList *sorted = NULL;
- rev = g_slist_sort(rev, (GCompareFunc) sp_compare_y_position);
- sorted = g_slist_sort(rev, (GCompareFunc) sp_compare_x_position);
-
-
- // Calculate individual Row and Column sizes if necessary
-
-
- cnt=0;
- const GSList *sizes = sorted;
- for (; sizes != NULL; sizes = sizes->next) {
- SPItem *item = SP_ITEM(sizes->data);
- Geom::OptRect b = item->documentVisualBounds();
- if (b) {
- width = b->dimensions()[Geom::X];
- height = b->dimensions()[Geom::Y];
- if (width > col_widths[(cnt % NoOfCols)]) {
- col_widths[(cnt % NoOfCols)] = width;
- }
- if (height > row_heights[(cnt / NoOfCols)]) {
- row_heights[(cnt / NoOfCols)] = height;
- }
- }
-
- cnt++;
- }
-
-
- /// Make sure the top and left of the grid dont move by compensating for align values.
- if (RowHeightButton.get_active()){
- grid_top = grid_top - (((row_height - row_heights[0]) / 2)*(VertAlign));
- }
- if (ColumnWidthButton.get_active()){
- grid_left = grid_left - (((col_width - col_widths[0]) /2)*(HorizAlign));
- }
-
- #ifdef DEBUG_GRID_ARRANGE
- g_print("\n cx = %f cy= %f gridleft=%f",cx,cy,grid_left);
- #endif
-
- // Calculate total widths and heights, allowing for columns and rows non uniformly sized.
+ _notebook.append_page(*_gridArrangeTab, C_("Arrange dialog", "Rectangular grid"));
+ _notebook.append_page(*_polarArrangeTab, C_("Arrange dialog", "Polar Coordinates"));
+ _arrangeBox.pack_start(_notebook);
- if (ColumnWidthButton.get_active()){
- total_col_width = col_width * NoOfCols;
- col_widths.clear();
- for (a=0;a<NoOfCols; a++){
- col_widths.push_back(col_width);
- }
- } else {
- for (a = 0; a < (int)col_widths.size(); a++)
- {
- total_col_width += col_widths[a] ;
- }
- }
-
- if (RowHeightButton.get_active()){
- total_row_height = row_height * NoOfRows;
- row_heights.clear();
- for (a=0;a<NoOfRows; a++){
- row_heights.push_back(row_height);
- }
- } else {
- for (a = 0; a < (int)row_heights.size(); a++)
- {
- total_row_height += row_heights[a] ;
- }
- }
-
-
- Geom::OptRect sel_bbox = selection->visualBounds();
- // Fit to bbox, calculate padding between rows accordingly.
- if ( sel_bbox && !SpaceManualRadioButton.get_active() ){
-#ifdef DEBUG_GRID_ARRANGE
-g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_height,total_col_width, b.extent(Geom::X), b.extent(Geom::Y));
-#endif
- paddingx = (sel_bbox->width() - total_col_width) / (NoOfCols -1);
- paddingy = (sel_bbox->height() - total_row_height) / (NoOfRows -1);
- }
-
-/*
- Horizontal align - Left = 0
- Centre = 1
- Right = 2
-
- Vertical align - Top = 0
- Middle = 1
- Bottom = 2
-
- X position is calculated by taking the grids left co-ord, adding the distance to the column,
- then adding 1/2 the spacing multiplied by the align variable above,
- Y position likewise, takes the top of the grid, adds the y to the current row then adds the padding in to align it.
-
-*/
-
- // Calculate row and column x and y coords required to allow for columns and rows which are non uniformly sized.
-
- for (a=0;a<NoOfCols; a++){
- if (a<1) col_xs.push_back(0);
- else col_xs.push_back(col_widths[a-1]+paddingx+col_xs[a-1]);
- }
-
-
- for (a=0;a<NoOfRows; a++){
- if (a<1) row_ys.push_back(0);
- else row_ys.push_back(row_heights[a-1]+paddingy+row_ys[a-1]);
- }
-
- cnt=0;
- for (row_cnt=0; ((sorted != NULL) && (row_cnt<NoOfRows)); row_cnt++) {
-
- GSList *current_row = NULL;
- for (col_cnt = 0; ((sorted != NULL) && (col_cnt<NoOfCols)); col_cnt++) {
- current_row = g_slist_append (current_row, sorted->data);
- sorted = sorted->next;
- }
-
- for (; current_row != NULL; current_row = current_row->next) {
- SPItem *item=SP_ITEM(current_row->data);
- Inkscape::XML::Node *repr = item->getRepr();
- Geom::OptRect b = item->documentVisualBounds();
- Geom::Point min;
- if (b) {
- width = b->dimensions()[Geom::X];
- height = b->dimensions()[Geom::Y];
- min = b->min();
- } else {
- width = height = 0;
- min = Geom::Point(0, 0);
- }
-
- row = cnt / NoOfCols;
- col = cnt % NoOfCols;
-
- new_x = grid_left + (((col_widths[col] - width)/2)*HorizAlign) + col_xs[col];
- new_y = grid_top + (((row_heights[row] - height)/2)*VertAlign) + row_ys[row];
-
- // signs are inverted between x and y due to y inversion
- Geom::Point move = Geom::Point(new_x - min[Geom::X], min[Geom::Y] - new_y);
- Geom::Affine const affine = Geom::Affine(Geom::Translate(move));
- item->set_i2d_affine(item->i2dt_affine() * affine);
- item->doWriteTransform(repr, item->transform, NULL);
- SP_OBJECT (current_row->data)->updateRepr();
- cnt +=1;
- }
- g_slist_free (current_row);
- }
-
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_GRIDTILE,
- _("Arrange in a grid"));
-
-}
-
-
-//#########################################################################
-//## E V E N T S
-//#########################################################################
-
-
-void TileDialog::_apply()
-{
- Grid_Arrange();
-}
-
-
-/**
- * changed value in # of columns spinbox.
- */
-void TileDialog::on_row_spinbutton_changed()
-{
- // quit if run by the attr_changed listener
- if (updating) {
- return;
- }
-
- // in turn, prevent listener from responding
- updating = true;
- SPDesktop *desktop = getDesktop();
-
- Inkscape::Selection *selection = desktop ? desktop->selection : 0;
- g_return_if_fail( selection );
-
- GSList const *items = selection->itemList();
- int selcount = g_slist_length((GSList *)items);
-
- double PerCol = ceil(selcount / NoOfColsSpinner.get_value());
- NoOfRowsSpinner.set_value(PerCol);
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setDouble("/dialogs/gridtiler/NoOfCols", NoOfColsSpinner.get_value());
- updating=false;
-}
-
-/**
- * changed value in # of rows spinbox.
- */
-void TileDialog::on_col_spinbutton_changed()
-{
- // quit if run by the attr_changed listener
- if (updating) {
- return;
- }
-
- // in turn, prevent listener from responding
- updating = true;
- SPDesktop *desktop = getDesktop();
- Inkscape::Selection *selection = desktop ? desktop->selection : 0;
- g_return_if_fail(selection);
-
- GSList const *items = selection->itemList();
- int selcount = g_slist_length((GSList *)items);
-
- double PerRow = ceil(selcount / NoOfRowsSpinner.get_value());
- NoOfColsSpinner.set_value(PerRow);
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setDouble("/dialogs/gridtiler/NoOfCols", PerRow);
-
- updating=false;
+ _arrangeButton = this->addResponseButton(C_("Arrange dialog","_Arrange"), GTK_RESPONSE_APPLY);
+ _arrangeButton->set_use_underline(true);
+ _arrangeButton->set_tooltip_text(_("Arrange selected objects"));
+ contents->pack_start(_arrangeBox);
+ //show_all_children();
}
-/**
- * changed value in x padding spinbox.
- */
-void TileDialog::on_xpad_spinbutton_changed()
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setDouble("/dialogs/gridtiler/XPad", XPadding.getValue("px"));
-}
-
-/**
- * changed value in y padding spinbox.
- */
-void TileDialog::on_ypad_spinbutton_changed()
+void ArrangeDialog::on_show()
{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setDouble("/dialogs/gridtiler/YPad", YPadding.getValue("px"));
+ UI::Widget::Panel::on_show();
+ _polarArrangeTab->on_arrange_radio_changed();
}
-
-/**
- * checked/unchecked autosize Rows button.
- */
-void TileDialog::on_RowSize_checkbutton_changed()
+void ArrangeDialog::_apply()
{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (RowHeightButton.get_active()) {
- prefs->setDouble("/dialogs/gridtiler/AutoRowSize", 20);
- } else {
- prefs->setDouble("/dialogs/gridtiler/AutoRowSize", -20);
- }
- RowHeightBox.set_sensitive ( !RowHeightButton.get_active());
-}
-
-/**
- * checked/unchecked autosize Rows button.
- */
-void TileDialog::on_ColSize_checkbutton_changed()
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (ColumnWidthButton.get_active()) {
- prefs->setDouble("/dialogs/gridtiler/AutoColSize", 20);
- } else {
- prefs->setDouble("/dialogs/gridtiler/AutoColSize", -20);
- }
- ColumnWidthBox.set_sensitive ( !ColumnWidthButton.get_active());
-}
-
-/**
- * changed value in columns spinbox.
- */
-void TileDialog::on_rowSize_spinbutton_changed()
-{
- // quit if run by the attr_changed listener
- if (updating) {
- return;
- }
-
- // in turn, prevent listener from responding
- updating = true;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setDouble("/dialogs/gridtiler/RowHeight", RowHeightSpinner.get_value());
- updating=false;
-
-}
-
-/**
- * changed value in rows spinbox.
- */
-void TileDialog::on_colSize_spinbutton_changed()
-{
- // quit if run by the attr_changed listener
- if (updating) {
- return;
- }
-
- // in turn, prevent listener from responding
- updating = true;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setDouble("/dialogs/gridtiler/ColWidth", ColumnWidthSpinner.get_value());
- updating=false;
-
-}
-
-/**
- * changed Radio button in Spacing group.
- */
-void TileDialog::Spacing_button_changed()
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (SpaceManualRadioButton.get_active()) {
- prefs->setDouble("/dialogs/gridtiler/SpacingType", 20);
- } else {
- prefs->setDouble("/dialogs/gridtiler/SpacingType", -20);
- }
-
- XPadding.set_sensitive ( SpaceManualRadioButton.get_active());
- YPadding.set_sensitive ( SpaceManualRadioButton.get_active());
-}
-
-/**
- * changed Radio button in Vertical Align group.
- */
-void TileDialog::VertAlign_changed()
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (VertTopRadioButton.get_active()) {
- VertAlign = 0;
- prefs->setInt("/dialogs/gridtiler/VertAlign", 0);
- } else if (VertCentreRadioButton.get_active()){
- VertAlign = 1;
- prefs->setInt("/dialogs/gridtiler/VertAlign", 1);
- } else if (VertBotRadioButton.get_active()){
- VertAlign = 2;
- prefs->setInt("/dialogs/gridtiler/VertAlign", 2);
- }
-}
-
-/**
- * changed Radio button in Vertical Align group.
- */
-void TileDialog::HorizAlign_changed()
-{
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (HorizLeftRadioButton.get_active()) {
- HorizAlign = 0;
- prefs->setInt("/dialogs/gridtiler/HorizAlign", 0);
- } else if (HorizCentreRadioButton.get_active()){
- HorizAlign = 1;
- prefs->setInt("/dialogs/gridtiler/HorizAlign", 1);
- } else if (HorizRightRadioButton.get_active()){
- HorizAlign = 2;
- prefs->setInt("/dialogs/gridtiler/HorizAlign", 2);
- }
-}
-
-/**
- * Desktop selection changed
- */
-void TileDialog::updateSelection()
-{
- // quit if run by the attr_changed listener
- if (updating) {
- return;
- }
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- // in turn, prevent listener from responding
- updating = true;
- SPDesktop *desktop = getDesktop();
- Inkscape::Selection *selection = desktop ? desktop->selection : 0;
- GSList const *items = selection ? selection->itemList() : 0;
-
- if (items) {
- int selcount = g_slist_length((GSList *)items);
-
- if (NoOfColsSpinner.get_value() > 1 && NoOfRowsSpinner.get_value() > 1){
- // Update the number of rows assuming number of columns wanted remains same.
- double NoOfRows = ceil(selcount / NoOfColsSpinner.get_value());
- NoOfRowsSpinner.set_value(NoOfRows);
-
- // if the selection has less than the number set for one row, reduce it appropriately
- if (selcount < NoOfColsSpinner.get_value()) {
- double NoOfCols = ceil(selcount / NoOfRowsSpinner.get_value());
- NoOfColsSpinner.set_value(NoOfCols);
- prefs->setInt("/dialogs/gridtiler/NoOfCols", NoOfCols);
- }
- } else {
- double PerRow = ceil(sqrt(selcount));
- double PerCol = ceil(sqrt(selcount));
- NoOfRowsSpinner.set_value(PerRow);
- NoOfColsSpinner.set_value(PerCol);
- prefs->setInt("/dialogs/gridtiler/NoOfCols", static_cast<int>(PerCol));
- }
- }
-
- updating = false;
-}
-
-
-
-/*##########################
-## Experimental
-##########################*/
-
-static void updateSelectionCallback(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, TileDialog *dlg)
-{
- dlg->updateSelection();
-}
-
-
-//#########################################################################
-//## C O N S T R U C T O R / D E S T R U C T O R
-//#########################################################################
-/**
- * Constructor
- */
-TileDialog::TileDialog()
- : UI::Widget::Panel("", "/dialogs/gridtiler", SP_VERB_SELECTION_GRIDTILE),
- XPadding(_("X:"), _("Horizontal spacing between columns."), UNIT_TYPE_LINEAR, "", "object-columns", &PaddingUnitMenu),
- YPadding(_("Y:"), _("Vertical spacing between rows."), UNIT_TYPE_LINEAR, "", "object-rows", &PaddingUnitMenu),
-#if WITH_GTKMM_3_0
- PaddingTable(Gtk::manage(new Gtk::Grid()))
-#else
- PaddingTable(Gtk::manage(new Gtk::Table(2, 2, false)))
-#endif
-{
- // bool used by spin button callbacks to stop loops where they change each other.
- updating = false;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
- // could not do this in gtkmm - there's no Gtk::SizeGroup public constructor (!)
- GtkSizeGroup *_col1 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- GtkSizeGroup *_col2 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
- GtkSizeGroup *_col3 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
-
- {
- // Selection Change signal
- g_signal_connect ( G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (updateSelectionCallback), this);
- }
-
- Gtk::Box *contents = _getContents();
-
-#define MARGIN 2
-
- //##Set up the panel
-
- SPDesktop *desktop = getDesktop();
-
- Inkscape::Selection *selection = desktop ? desktop->selection : 0;
- g_return_if_fail( selection );
- int selcount = 1;
- if (!selection->isEmpty()) {
- GSList const *items = selection->itemList();
- selcount = g_slist_length((GSList *)items);
- }
-
-
- /*#### Number of Rows ####*/
-
- double PerRow = ceil(sqrt(selcount));
- double PerCol = ceil(sqrt(selcount));
-
- #ifdef DEBUG_GRID_ARRANGE
- g_print("/n PerRox = %f PerCol = %f selcount = %d",PerRow,PerCol,selcount);
- #endif
-
- NoOfRowsLabel.set_text_with_mnemonic(_("_Rows:"));
- NoOfRowsLabel.set_mnemonic_widget(NoOfRowsSpinner);
- NoOfRowsBox.pack_start(NoOfRowsLabel, false, false, MARGIN);
-
- NoOfRowsSpinner.set_digits(0);
- NoOfRowsSpinner.set_increments(1, 0);
- NoOfRowsSpinner.set_range(1.0, 10000.0);
- NoOfRowsSpinner.set_value(PerCol);
- NoOfRowsSpinner.signal_changed().connect(sigc::mem_fun(*this, &TileDialog::on_col_spinbutton_changed));
- NoOfRowsSpinner.set_tooltip_text(_("Number of rows"));
- NoOfRowsBox.pack_start(NoOfRowsSpinner, false, false, MARGIN);
- gtk_size_group_add_widget(_col1, GTK_WIDGET(NoOfRowsBox.gobj()));
-
- RowHeightButton.set_label(_("Equal _height"));
- RowHeightButton.set_use_underline(true);
- double AutoRow = prefs->getDouble("/dialogs/gridtiler/AutoRowSize", 15);
- if (AutoRow>0)
- AutoRowSize=true;
- else
- AutoRowSize=false;
- RowHeightButton.set_active(AutoRowSize);
-
- NoOfRowsBox.pack_start(RowHeightButton, false, false, MARGIN);
-
- RowHeightButton.set_tooltip_text(_("If not set, each row has the height of the tallest object in it"));
- RowHeightButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::on_RowSize_checkbutton_changed));
-
- {
- /*#### Radio buttons to control vertical alignment ####*/
-
- VertAlignLabel.set_label(_("Align:"));
- VertAlignHBox.pack_start(VertAlignLabel, false, false, MARGIN);
-
- VertTopRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::VertAlign_changed));
- VertAlignGroup = VertTopRadioButton.get_group();
- VertAlignVBox.pack_start(VertTopRadioButton, false, false, 0);
-
- VertCentreRadioButton.set_group(VertAlignGroup);
- VertCentreRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::VertAlign_changed));
- VertAlignVBox.pack_start(VertCentreRadioButton, false, false, 0);
-
- VertBotRadioButton.set_group(VertAlignGroup);
- VertBotRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::VertAlign_changed));
- VertAlignVBox.pack_start(VertBotRadioButton, false, false, 0);
-
- VertAlign = prefs->getInt("/dialogs/gridtiler/VertAlign", 1);
- if (VertAlign == 0) {
- VertTopRadioButton.set_active(TRUE);
- }
- else if (VertAlign == 1) {
- VertCentreRadioButton.set_active(TRUE);
- }
- else if (VertAlign == 2){
- VertBotRadioButton.set_active(TRUE);
- }
- VertAlignHBox.pack_start(VertAlignVBox, false, false, MARGIN);
- NoOfRowsBox.pack_start(VertAlignHBox, false, false, MARGIN);
- }
-
- SpinsHBox.pack_start(NoOfRowsBox, false, false, MARGIN);
-
-
- /*#### Label for X ####*/
- padXByYLabel.set_label(" ");
- XByYLabelVBox.pack_start(padXByYLabel, false, false, MARGIN);
- XByYLabel.set_markup(" &#215; ");
- XByYLabelVBox.pack_start(XByYLabel, false, false, MARGIN);
- SpinsHBox.pack_start(XByYLabelVBox, false, false, MARGIN);
- gtk_size_group_add_widget(_col2, GTK_WIDGET(XByYLabelVBox.gobj()));
-
- /*#### Number of columns ####*/
-
- NoOfColsLabel.set_text_with_mnemonic(_("_Columns:"));
- NoOfColsLabel.set_mnemonic_widget(NoOfColsSpinner);
- NoOfColsBox.pack_start(NoOfColsLabel, false, false, MARGIN);
-
- NoOfColsSpinner.set_digits(0);
- NoOfColsSpinner.set_increments(1, 0);
- NoOfColsSpinner.set_range(1.0, 10000.0);
- NoOfColsSpinner.set_value(PerRow);
- NoOfColsSpinner.signal_changed().connect(sigc::mem_fun(*this, &TileDialog::on_row_spinbutton_changed));
- NoOfColsSpinner.set_tooltip_text(_("Number of columns"));
- NoOfColsBox.pack_start(NoOfColsSpinner, false, false, MARGIN);
- gtk_size_group_add_widget(_col3, GTK_WIDGET(NoOfColsBox.gobj()));
-
- ColumnWidthButton.set_label(_("Equal _width"));
- ColumnWidthButton.set_use_underline(true);
- double AutoCol = prefs->getDouble("/dialogs/gridtiler/AutoColSize", 15);
- if (AutoCol>0)
- AutoColSize=true;
- else
- AutoColSize=false;
- ColumnWidthButton.set_active(AutoColSize);
- NoOfColsBox.pack_start(ColumnWidthButton, false, false, MARGIN);
-
- ColumnWidthButton.set_tooltip_text(_("If not set, each column has the width of the widest object in it"));
- ColumnWidthButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::on_ColSize_checkbutton_changed));
-
-
- {
- /*#### Radio buttons to control horizontal alignment ####*/
-
- HorizAlignLabel.set_label(_("Align:"));
- HorizAlignVBox.pack_start(HorizAlignLabel, false, false, MARGIN);
-
- HorizAlignHBox.pack_start(*(new Gtk::HBox()), true, true, 0); // centering strut
-
- HorizLeftRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::HorizAlign_changed));
- HorizAlignGroup = HorizLeftRadioButton.get_group();
- HorizAlignHBox.pack_start(HorizLeftRadioButton, false, false, 0);
-
- HorizCentreRadioButton.set_group(HorizAlignGroup);
- HorizCentreRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::HorizAlign_changed));
- HorizAlignHBox.pack_start(HorizCentreRadioButton, false, false, 0);
-
- HorizRightRadioButton.set_group(HorizAlignGroup);
- HorizRightRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::HorizAlign_changed));
- HorizAlignHBox.pack_start(HorizRightRadioButton, false, false, 0);
-
- HorizAlignHBox.pack_start(*(new Gtk::HBox()), true, true, 0); // centering strut
-
- HorizAlign = prefs->getInt("/dialogs/gridtiler/HorizAlign", 1);
- if (HorizAlign == 0) {
- HorizLeftRadioButton.set_active(TRUE);
- }
- else if (HorizAlign == 1) {
- HorizCentreRadioButton.set_active(TRUE);
- }
- else if (HorizAlign == 2) {
- HorizRightRadioButton.set_active(TRUE);
- }
- HorizAlignVBox.pack_start(HorizAlignHBox, false, false, MARGIN);
- NoOfColsBox.pack_start(HorizAlignVBox, false, false, MARGIN);
- }
-
- SpinsHBox.pack_start(NoOfColsBox, false, false, MARGIN);
-
- TileBox.pack_start(SpinsHBox, false, false, MARGIN);
-
- {
- /*#### Radio buttons to control spacing manually or to fit selection bbox ####*/
- SpaceByBBoxRadioButton.set_label(_("_Fit into selection box"));
- SpaceByBBoxRadioButton.set_use_underline (true);
- SpaceByBBoxRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::Spacing_button_changed));
- SpacingGroup = SpaceByBBoxRadioButton.get_group();
-
- SpacingVBox.pack_start(SpaceByBBoxRadioButton, false, false, MARGIN);
-
- SpaceManualRadioButton.set_label(_("_Set spacing:"));
- SpaceManualRadioButton.set_use_underline (true);
- SpaceManualRadioButton.set_group(SpacingGroup);
- SpaceManualRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::Spacing_button_changed));
- SpacingVBox.pack_start(SpaceManualRadioButton, false, false, MARGIN);
-
- TileBox.pack_start(SpacingVBox, false, false, MARGIN);
- }
-
- {
- /*#### Padding ####*/
- PaddingUnitMenu.setUnitType(UNIT_TYPE_LINEAR);
- PaddingUnitMenu.setUnit("px");
-
- YPadding.setDigits(5);
- YPadding.setIncrements(0.2, 0);
- YPadding.setRange(-10000, 10000);
- double yPad = prefs->getDouble("/dialogs/gridtiler/YPad", 15);
- YPadding.setValue(yPad, "px");
- YPadding.signal_value_changed().connect(sigc::mem_fun(*this, &TileDialog::on_ypad_spinbutton_changed));
-
- XPadding.setDigits(5);
- XPadding.setIncrements(0.2, 0);
- XPadding.setRange(-10000, 10000);
- double xPad = prefs->getDouble("/dialogs/gridtiler/XPad", 15);
- XPadding.setValue(xPad, "px");
-
- XPadding.signal_value_changed().connect(sigc::mem_fun(*this, &TileDialog::on_xpad_spinbutton_changed));
- }
-
- PaddingTable->set_border_width(MARGIN);
-
-#if WITH_GTKMM_3_0
- PaddingTable->set_row_spacing(MARGIN);
- PaddingTable->set_column_spacing(MARGIN);
- PaddingTable->attach(XPadding, 0, 0, 1, 1);
- PaddingTable->attach(PaddingUnitMenu, 1, 0, 1, 1);
- PaddingTable->attach(YPadding, 0, 1, 1, 1);
-#else
- PaddingTable->set_row_spacings(MARGIN);
- PaddingTable->set_col_spacings(MARGIN);
- PaddingTable->attach(XPadding, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
- PaddingTable->attach(PaddingUnitMenu, 1, 2, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
- PaddingTable->attach(YPadding, 0, 1, 1, 2, Gtk::SHRINK, Gtk::SHRINK);
-#endif
-
- TileBox.pack_start(*PaddingTable, false, false, MARGIN);
-
- contents->pack_start(TileBox);
-
- double SpacingType = prefs->getDouble("/dialogs/gridtiler/SpacingType", 15);
- if (SpacingType>0) {
- ManualSpacing=true;
- } else {
- ManualSpacing=false;
- }
- SpaceManualRadioButton.set_active(ManualSpacing);
- SpaceByBBoxRadioButton.set_active(!ManualSpacing);
- XPadding.set_sensitive (ManualSpacing);
- YPadding.set_sensitive (ManualSpacing);
-
- //## The OK button
- TileOkButton = addResponseButton(C_("Rows and columns dialog","_Arrange"), GTK_RESPONSE_APPLY);
- TileOkButton->set_use_underline(true);
- TileOkButton->set_tooltip_text(_("Arrange selected objects"));
-
- show_all_children();
+ switch(_notebook.get_current_page())
+ {
+ case 0:
+ _gridArrangeTab->arrange();
+ break;
+ case 1:
+ _polarArrangeTab->arrange();
+ break;
+ }
}
} //namespace Dialog
diff --git a/src/ui/dialog/tile.h b/src/ui/dialog/tile.h
index 6e41723fd..2f75a8922 100644
--- a/src/ui/dialog/tile.h
+++ b/src/ui/dialog/tile.h
@@ -5,6 +5,7 @@
* Bob Jamison ( based off trace dialog)
* John Cliff
* Other dudes from The Inkscape Organization
+ * Declara Denis
*
* Copyright (C) 2004 Bob Jamison
* Copyright (C) 2004 John Cliff
@@ -29,8 +30,6 @@
#include <gtkmm/radiobutton.h>
#include "ui/widget/panel.h"
-#include "ui/widget/spinbutton.h"
-#include "ui/widget/scalar-unit.h"
namespace Gtk {
class Button;
@@ -46,134 +45,34 @@ namespace Inkscape {
namespace UI {
namespace Dialog {
+class ArrangeTab;
+class GridArrangeTab;
+class PolarArrangeTab;
-/**
- * Dialog for tiling an object
- */
-class TileDialog : public UI::Widget::Panel {
-public:
- TileDialog() ;
- virtual ~TileDialog() {};
+class ArrangeDialog : public UI::Widget::Panel {
+private:
+ Gtk::VBox _arrangeBox;
+ Gtk::Notebook _notebook;
- /**
- * Do the actual work
- */
- void Grid_Arrange();
+ GridArrangeTab *_gridArrangeTab;
+ PolarArrangeTab *_polarArrangeTab;
- /**
- * Respond to selection change
- */
- void updateSelection();
+ Gtk::Button *_arrangeButton;
+
+public:
+ ArrangeDialog();
+ virtual ~ArrangeDialog() {};
/**
* Callback from Apply
*/
virtual void _apply();
- // Callbacks from spinbuttons
- void on_row_spinbutton_changed();
- void on_col_spinbutton_changed();
- void on_xpad_spinbutton_changed();
- void on_ypad_spinbutton_changed();
- void on_RowSize_checkbutton_changed();
- void on_ColSize_checkbutton_changed();
- void on_rowSize_spinbutton_changed();
- void on_colSize_spinbutton_changed();
- void Spacing_button_changed();
- void VertAlign_changed();
- void HorizAlign_changed();
-
- static TileDialog& getInstance() { return *new TileDialog(); }
-
-private:
- TileDialog(TileDialog const &d); // no copy
- void operator=(TileDialog const &d); // no assign
-
- bool userHidden;
- bool updating;
-
- Gtk::Notebook notebook;
-
- Gtk::VBox TileBox;
- Gtk::Button *TileOkButton;
- Gtk::Button *TileCancelButton;
-
- // Number selected label
- Gtk::Label SelectionContentsLabel;
-
-
- Gtk::HBox AlignHBox;
- Gtk::HBox SpinsHBox;
-
- // Number per Row
- Gtk::VBox NoOfColsBox;
- Gtk::Label NoOfColsLabel;
- Inkscape::UI::Widget::SpinButton NoOfColsSpinner;
- bool AutoRowSize;
- Gtk::CheckButton RowHeightButton;
-
- Gtk::VBox XByYLabelVBox;
- Gtk::Label padXByYLabel;
- Gtk::Label XByYLabel;
-
- // Number per Column
- Gtk::VBox NoOfRowsBox;
- Gtk::Label NoOfRowsLabel;
- Inkscape::UI::Widget::SpinButton NoOfRowsSpinner;
- bool AutoColSize;
- Gtk::CheckButton ColumnWidthButton;
-
- // Vertical align
- Gtk::Label VertAlignLabel;
- Gtk::HBox VertAlignHBox;
- Gtk::VBox VertAlignVBox;
- Gtk::RadioButtonGroup VertAlignGroup;
- Gtk::RadioButton VertCentreRadioButton;
- Gtk::RadioButton VertTopRadioButton;
- Gtk::RadioButton VertBotRadioButton;
- double VertAlign;
-
- // Horizontal align
- Gtk::Label HorizAlignLabel;
- Gtk::VBox HorizAlignVBox;
- Gtk::HBox HorizAlignHBox;
- Gtk::RadioButtonGroup HorizAlignGroup;
- Gtk::RadioButton HorizCentreRadioButton;
- Gtk::RadioButton HorizLeftRadioButton;
- Gtk::RadioButton HorizRightRadioButton;
- double HorizAlign;
-
- Inkscape::UI::Widget::UnitMenu PaddingUnitMenu;
- Inkscape::UI::Widget::ScalarUnit XPadding;
- Inkscape::UI::Widget::ScalarUnit YPadding;
-
-#if WITH_GTKMM_3_0
- Gtk::Grid *PaddingTable;
-#else
- Gtk::Table *PaddingTable;
-#endif
+ virtual void on_show();
- // BBox or manual spacing
- Gtk::VBox SpacingVBox;
- Gtk::RadioButtonGroup SpacingGroup;
- Gtk::RadioButton SpaceByBBoxRadioButton;
- Gtk::RadioButton SpaceManualRadioButton;
- bool ManualSpacing;
-
- // Row height
- Gtk::VBox RowHeightVBox;
- Gtk::HBox RowHeightBox;
- Gtk::Label RowHeightLabel;
- Inkscape::UI::Widget::SpinButton RowHeightSpinner;
-
- // Column width
- Gtk::VBox ColumnWidthVBox;
- Gtk::HBox ColumnWidthBox;
- Gtk::Label ColumnWidthLabel;
- Inkscape::UI::Widget::SpinButton ColumnWidthSpinner;
+ static ArrangeDialog& getInstance() { return *new ArrangeDialog(); }
};
-
} //namespace Dialog
} //namespace UI
} //namespace Inkscape
diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp
index e19f35832..4f918b483 100644
--- a/src/ui/tools/connector-tool.cpp
+++ b/src/ui/tools/connector-tool.cpp
@@ -201,7 +201,8 @@ ConnectorTool::~ConnectorTool() {
for (int i = 0; i < 2; ++i) {
if (this->endpt_handle[1]) {
- g_object_unref(this->endpt_handle[i]);
+ //g_object_unref(this->endpt_handle[i]);
+ knot_unref(this->endpt_handle[i]);
this->endpt_handle[i] = NULL;
}
}
@@ -319,7 +320,7 @@ cc_clear_active_knots(SPKnotList k)
// Hide the connection points if they exist.
if (k.size()) {
for (SPKnotList::iterator it = k.begin(); it != k.end(); ++it) {
- sp_knot_hide(it->first);
+ it->first->hide();
}
}
}
@@ -341,7 +342,7 @@ void ConnectorTool::cc_clear_active_conn() {
// Hide the endpoint handles.
for (int i = 0; i < 2; ++i) {
if (this->endpt_handle[i]) {
- sp_knot_hide(this->endpt_handle[i]);
+ this->endpt_handle[i]->hide();
}
}
}
@@ -365,7 +366,7 @@ cc_select_handle(SPKnot* knot)
knot->setSize(10);
knot->setAnchor(SP_ANCHOR_CENTER);
knot->setFill(0x0000ffff, 0x0000ffff, 0x0000ffff);
- sp_knot_update_ctrl(knot);
+ knot->update_ctrl();
}
static void
@@ -375,7 +376,7 @@ cc_deselect_handle(SPKnot* knot)
knot->setSize(8);
knot->setAnchor(SP_ANCHOR_CENTER);
knot->setFill(0xffffff00, 0xff0000ff, 0xff0000ff);
- sp_knot_update_ctrl(knot);
+ knot->update_ctrl();
}
bool ConnectorTool::item_handler(SPItem* item, GdkEvent* event) {
@@ -969,7 +970,8 @@ cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot)
{
g_assert (knot != NULL);
- g_object_ref(knot);
+ //g_object_ref(knot);
+ knot_ref(knot);
ConnectorTool *cc = SP_CONNECTOR_CONTEXT(
knot->desktop->event_context);
@@ -979,7 +981,7 @@ cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot)
gchar const *knot_tip = "Click to join at this point";
switch (event->type) {
case GDK_ENTER_NOTIFY:
- sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, TRUE);
+ knot->set_flag(SP_KNOT_MOUSEOVER, TRUE);
cc->active_handle = knot;
if (knot_tip)
@@ -991,7 +993,7 @@ cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot)
consumed = TRUE;
break;
case GDK_LEAVE_NOTIFY:
- sp_knot_set_flag(knot, SP_KNOT_MOUSEOVER, FALSE);
+ knot->set_flag(SP_KNOT_MOUSEOVER, FALSE);
/* FIXME: the following test is a workaround for LP Bug #1273510.
* It seems that a signal is not correctly disconnected, maybe
@@ -1010,7 +1012,8 @@ cc_generic_knot_handler(SPCanvasItem *, GdkEvent *event, SPKnot *knot)
break;
}
- g_object_unref(knot);
+ //g_object_unref(knot);
+ knot_unref(knot);
return consumed;
}
@@ -1066,14 +1069,14 @@ endpt_handler(SPKnot */*knot*/, GdkEvent *event, ConnectorTool *cc)
}
void ConnectorTool::_activeShapeAddKnot(SPItem* item) {
- SPKnot *knot = sp_knot_new(desktop, 0);
+ SPKnot *knot = new SPKnot(desktop, 0);
knot->owner = item;
knot->setShape(SP_KNOT_SHAPE_SQUARE);
knot->setSize(8);
knot->setAnchor(SP_ANCHOR_CENTER);
knot->setFill(0xffffff00, 0xff0000ff, 0xff0000ff);
- sp_knot_update_ctrl(knot);
+ knot->update_ctrl();
// We don't want to use the standard knot handler.
g_signal_handler_disconnect(G_OBJECT(knot->item),
@@ -1084,8 +1087,8 @@ void ConnectorTool::_activeShapeAddKnot(SPItem* item) {
g_signal_connect(G_OBJECT(knot->item), "event",
G_CALLBACK(cc_generic_knot_handler), knot);
- sp_knot_set_position(knot, item->avoidRef->getConnectionPointPos() * desktop->doc2dt(), 0);
- sp_knot_show(knot);
+ knot->set_position(item->avoidRef->getConnectionPointPos() * desktop->doc2dt(), 0);
+ knot->show();
this->knots[knot] = 1;
}
@@ -1149,17 +1152,17 @@ void ConnectorTool::cc_set_active_conn(SPItem *item) {
{
// Connector is invisible because it is clipped to the boundary of
// two overlpapping shapes.
- sp_knot_hide(this->endpt_handle[0]);
- sp_knot_hide(this->endpt_handle[1]);
+ this->endpt_handle[0]->hide();
+ this->endpt_handle[1]->hide();
}
else
{
// Just adjust handle positions.
Geom::Point startpt = *(curve->first_point()) * i2dt;
- sp_knot_set_position(this->endpt_handle[0], startpt, 0);
+ this->endpt_handle[0]->set_position(startpt, 0);
Geom::Point endpt = *(curve->last_point()) * i2dt;
- sp_knot_set_position(this->endpt_handle[1], endpt, 0);
+ this->endpt_handle[1]->set_position(endpt, 0);
}
return;
@@ -1184,7 +1187,7 @@ void ConnectorTool::cc_set_active_conn(SPItem *item) {
for (int i = 0; i < 2; ++i) {
// Create the handle if it doesn't exist
if ( this->endpt_handle[i] == NULL ) {
- SPKnot *knot = sp_knot_new(this->desktop,
+ SPKnot *knot = new SPKnot(this->desktop,
_("<b>Connector endpoint</b>: drag to reroute or connect to new shapes"));
knot->setShape(SP_KNOT_SHAPE_SQUARE);
@@ -1192,7 +1195,7 @@ void ConnectorTool::cc_set_active_conn(SPItem *item) {
knot->setAnchor(SP_ANCHOR_CENTER);
knot->setFill(0xffffff00, 0xff0000ff, 0xff0000ff);
knot->setStroke(0x000000ff, 0x000000ff, 0x000000ff);
- sp_knot_update_ctrl(knot);
+ knot->update_ctrl();
// We don't want to use the standard knot handler,
// since we don't want this knot to be draggable.
@@ -1232,13 +1235,13 @@ void ConnectorTool::cc_set_active_conn(SPItem *item) {
}
Geom::Point startpt = *(curve->first_point()) * i2dt;
- sp_knot_set_position(this->endpt_handle[0], startpt, 0);
+ this->endpt_handle[0]->set_position(startpt, 0);
Geom::Point endpt = *(curve->last_point()) * i2dt;
- sp_knot_set_position(this->endpt_handle[1], endpt, 0);
+ this->endpt_handle[1]->set_position(endpt, 0);
- sp_knot_show(this->endpt_handle[0]);
- sp_knot_show(this->endpt_handle[1]);
+ this->endpt_handle[0]->show();
+ this->endpt_handle[1]->show();
}
void cc_create_connection_point(ConnectorTool* cc)
@@ -1250,7 +1253,7 @@ void cc_create_connection_point(ConnectorTool* cc)
cc_deselect_handle( cc->selected_handle );
}
- SPKnot *knot = sp_knot_new(cc->desktop, 0);
+ SPKnot *knot = new SPKnot(cc->desktop, 0);
// We do not process events on this knot.
g_signal_handler_disconnect(G_OBJECT(knot->item),
@@ -1260,7 +1263,7 @@ void cc_create_connection_point(ConnectorTool* cc)
cc_select_handle( knot );
cc->selected_handle = knot;
- sp_knot_show(cc->selected_handle);
+ cc->selected_handle->show();
cc->state = SP_CONNECTOR_CONTEXT_NEWCONNPOINT;
}
}
diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert
index 196004df1..e18b790bd 100644
--- a/src/ui/widget/Makefile_insert
+++ b/src/ui/widget/Makefile_insert
@@ -1,6 +1,8 @@
## Makefile.am fragment sourced by src/Makefile.am.
ink_common_sources += \
+ ui/widget/anchor-selector.h \
+ ui/widget/anchor-selector.cpp \
ui/widget/attr-widget.h \
ui/widget/button.h \
ui/widget/button.cpp \
diff --git a/src/ui/widget/anchor-selector.cpp b/src/ui/widget/anchor-selector.cpp
new file mode 100644
index 000000000..82e27ee89
--- /dev/null
+++ b/src/ui/widget/anchor-selector.cpp
@@ -0,0 +1,97 @@
+/*
+ * anchor-selector.cpp
+ *
+ * Created on: Mar 22, 2012
+ * Author: denis
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#include "ui/widget/anchor-selector.h"
+#include <iostream>
+#include "widgets/icon.h"
+#include "ui/icon-names.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+void AnchorSelector::setupButton(const Glib::ustring& icon, Gtk::ToggleButton& button) {
+ Gtk::Widget* buttonIcon = Gtk::manage(sp_icon_get_icon(icon, Inkscape::ICON_SIZE_SMALL_TOOLBAR));
+ buttonIcon->show();
+
+ button.set_relief(Gtk::RELIEF_NONE);
+ button.show();
+ button.add(*buttonIcon);
+ button.set_can_focus(false);
+}
+
+AnchorSelector::AnchorSelector()
+ : Gtk::Alignment(0.5, 0, 0, 0),
+ _container(3, 3, true)
+{
+ setupButton(INKSCAPE_ICON("boundingbox_top_left"), _buttons[0]);
+ setupButton(INKSCAPE_ICON("boundingbox_top"), _buttons[1]);
+ setupButton(INKSCAPE_ICON("boundingbox_top_right"), _buttons[2]);
+ setupButton(INKSCAPE_ICON("boundingbox_left"), _buttons[3]);
+ setupButton(INKSCAPE_ICON("boundingbox_center"), _buttons[4]);
+ setupButton(INKSCAPE_ICON("boundingbox_right"), _buttons[5]);
+ setupButton(INKSCAPE_ICON("boundingbox_bottom_left"), _buttons[6]);
+ setupButton(INKSCAPE_ICON("boundingbox_bottom"), _buttons[7]);
+ setupButton(INKSCAPE_ICON("boundingbox_bottom_right"), _buttons[8]);
+
+ for(int i = 0; i < 9; ++i) {
+ _buttons[i].signal_clicked().connect(
+ sigc::bind(sigc::mem_fun(*this, &AnchorSelector::btn_activated), i));
+ _container.attach(_buttons[i], i % 3, i % 3+1, i / 3, i / 3+1, Gtk::FILL, Gtk::FILL);
+ }
+ _selection = 4;
+ _buttons[4].set_active();
+
+ this->add(_container);
+}
+
+AnchorSelector::~AnchorSelector()
+{
+ // TODO Auto-generated destructor stub
+}
+
+void AnchorSelector::btn_activated(int index)
+{
+
+ if(_selection == index && _buttons[index].get_active() == false)
+ {
+ _buttons[index].set_active(true);
+ }
+ else if(_selection != index && _buttons[index].get_active())
+ {
+ int old_selection = _selection;
+ _selection = index;
+ _buttons[old_selection].set_active(false);
+ _selectionChanged.emit();
+ }
+}
+
+void AnchorSelector::setAlignment(int horizontal, int vertical)
+{
+ int index = 3 * vertical + horizontal;
+ if(index >= 0 && index < 9)
+ {
+ _buttons[index].set_active(!_buttons[index].get_active());
+ }
+}
+
+} // 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/anchor-selector.h b/src/ui/widget/anchor-selector.h
new file mode 100644
index 000000000..2263438e3
--- /dev/null
+++ b/src/ui/widget/anchor-selector.h
@@ -0,0 +1,59 @@
+/*
+ * anchor-selector.h
+ *
+ * Created on: Mar 22, 2012
+ * Author: denis
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information.
+ */
+
+#ifndef ANCHOR_SELECTOR_H_
+#define ANCHOR_SELECTOR_H_
+
+#include <gtkmm.h>
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+class AnchorSelector : public Gtk::Alignment
+{
+private:
+ Gtk::ToggleButton _buttons[9];
+ int _selection;
+ Gtk::Table _container;
+
+ sigc::signal<void> _selectionChanged;
+
+ void setupButton(const Glib::ustring &icon, Gtk::ToggleButton &button);
+ void btn_activated(int index);
+
+public:
+
+ int getHorizontalAlignment() { return _selection % 3; }
+ int getVerticalAlignment() { return _selection / 3; }
+
+ sigc::signal<void> &on_selectionChanged() { return _selectionChanged; }
+
+ void setAlignment(int horizontal, int vertical);
+
+ AnchorSelector();
+ virtual ~AnchorSelector();
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif /* ANCHOR_SELECTOR_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 :