/* * 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 * * 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 #ifdef HAVE_CONFIG_H # include #endif #include "tile.h" #include //for GTK_RESPONSE* types #include #include #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" /* * 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 */ 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. */ 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 { ArrangeDialog::ArrangeDialog() : UI::Widget::Panel("", "/dialogs/gridtiler", SP_VERB_SELECTION_GRIDTILE), _gridArrangeTab(new GridArrangeTab(this)), _polarArrangeTab(new PolarArrangeTab(this)) { Gtk::Box *contents = this->_getContents(); _notebook.append_page(*_gridArrangeTab, C_("Arrange dialog", "Rectangular grid")); _notebook.append_page(*_polarArrangeTab, C_("Arrange dialog", "Polar Coordinates")); _arrangeBox.pack_start(_notebook); _arrangeButton = this->addResponseButton(C_("Arrange dialog","_Arrange"), GTK_RESPONSE_APPLY); _arrangeButton->set_use_underline(true); _arrangeButton->set_tooltip_text(_("Arrange selected objects")); _arrangeBox.pack_start(*_arrangeButton); contents->pack_start(_arrangeBox); show_all_children(); } void ArrangeDialog::_apply() { switch(_notebook.get_current_page()) { case 0: _gridArrangeTab->arrange(); break; case 1: _polarArrangeTab->arrange(); break; } } 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("Anchor point:"); anchorPointLabel.set_alignment(Gtk::ALIGN_START); pack_start(anchorPointLabel, false, false); anchorBoundingBoxRadio.set_label("Object's bounding box:"); anchorRadioGroup = anchorBoundingBoxRadio.get_group(); pack_start(anchorBoundingBoxRadio, false, false); pack_start(anchorSelector, false, false); anchorObjectPivotRadio.set_label("Object's rotational center"); anchorObjectPivotRadio.set_group(anchorRadioGroup); pack_start(anchorObjectPivotRadio, false, false); arrangeOnLabel.set_text("Arrange on:"); arrangeOnLabel.set_alignment(Gtk::ALIGN_START); pack_start(arrangeOnLabel, false, false); arrangeOnCircleRadio.set_label("Last selected circle/ellipse/arc"); arrangeRadioGroup = arrangeOnCircleRadio.get_group(); pack_start(arrangeOnCircleRadio, false, false); arrangeOnParametersRadio.set_label("Parameterized:"); arrangeOnParametersRadio.set_group(arrangeRadioGroup); pack_start(arrangeOnParametersRadio, false, false); centerLabel.set_text("Center X/Y:"); parametersTable.attach(centerLabel, 0, 1, 0, 1); parametersTable.attach(centerX, 1, 2, 0, 1, Gtk::EXPAND); parametersTable.attach(centerY, 2, 3, 0, 1, Gtk::EXPAND); radiusLabel.set_text("Radius X/Y:"); parametersTable.attach(radiusLabel, 0, 1, 1, 2); parametersTable.attach(radiusX, 1, 2, 1, 2, Gtk::EXPAND); parametersTable.attach(radiusY, 2, 3, 1, 2, Gtk::EXPAND); angleLabel.set_text("Center X/Y:"); parametersTable.attach(angleLabel, 0, 1, 2, 3); parametersTable.attach(angleX, 1, 2, 2, 3, Gtk::EXPAND); parametersTable.attach(angleY, 2, 3, 2, 3, Gtk::EXPAND); pack_start(parametersTable, false, false); } void PolarArrangeTab::arrange() { std::cout << "PolarArrangeTab::arrange()" << std::endl; } void PolarArrangeTab::updateSelection() { } //######################################################################### //## 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,cx,cy; 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 row_heights; std::vector col_widths; std::vector row_ys; std::vector col_xs; int NoOfCols = NoOfColsSpinner.get_value_as_int(); int NoOfRows = NoOfRowsSpinner.get_value_as_int(); width = 0; for (a=0;agetDesktop(); 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]; cx = b->midpoint()[Geom::X]; cy = b->midpoint()[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((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;avisualBounds(); // 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;adata); 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 //######################################################################### /** * 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(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"), YPadding(_("Y:"), _("Vertical spacing between rows."), XPadding, "", "object-rows") { // 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(" × "); XByYLabelVBox.pack_start(XByYLabel, false, false, MARGIN); SpinsHBox.pack_start(XByYLabelVBox, false, false, MARGIN); gtk_size_group_add_widget(_col2, (GtkWidget *) 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, (GtkWidget *) 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 ####*/ 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)); } TileBox.pack_start(XPadding, false, false, MARGIN); TileBox.pack_start(YPadding, 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 :