X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdesktop.cpp;h=932d79ff2e7dadfe24d1c6e3cee85e5db55c0d79;hb=9e973c4fb2183b877bb600a7e9c75e93b3e7d6d1;hp=d31babf87cb1f365a0dfe11e95353fc912ace79d;hpb=1e7c268648bcbae15fc13b8c94dee677b401d9b3;p=inkscape.git diff --git a/src/desktop.cpp b/src/desktop.cpp index d31babf87..932d79ff2 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -12,7 +12,7 @@ * Johan Engelen * * Copyright (C) 2007 Jon A. Cruz - * Copyright (C) 2006-2007 Johan Engelen + * Copyright (C) 2006-2008 Johan Engelen * Copyright (C) 2006 John Bintz * Copyright (C) 2004 MenTaLguY * Copyright (C) 1999-2002 Lauris Kaplinski @@ -77,14 +77,20 @@ #include "display/gnome-canvas-acetate.h" #include "display/sodipodi-ctrlrect.h" #include "display/sp-canvas-util.h" +#include "display/canvas-temporary-item-list.h" +#include "display/snap-indicator.h" #include "libnr/nr-matrix-div.h" #include "libnr/nr-rect-ops.h" #include "ui/dialog/dialog-manager.h" #include "xml/repr.h" #include "message-context.h" +#include "device-manager.h" +#include "layer-fns.h" #include "layer-manager.h" #include "event-log.h" #include "display/canvas-grid.h" +#include "widgets/desktop-widget.h" +#include "box3d-context.h" #include "display/sp-canvas.h" @@ -114,6 +120,8 @@ SPDesktop::SPDesktop() : event_context( 0 ), layer_manager( 0 ), event_log( 0 ), + temporary_item_list( 0 ), + snapindicator( 0 ), acetate( 0 ), main( 0 ), gridgroup( 0 ), @@ -121,6 +129,7 @@ SPDesktop::SPDesktop() : drawing( 0 ), sketch( 0 ), controls( 0 ), + tempgroup ( 0 ), table( 0 ), page( 0 ), page_border( 0 ), @@ -139,6 +148,8 @@ SPDesktop::SPDesktop() : gr_fill_or_stroke( true ), _layer_hierarchy( 0 ), _reconstruction_old_layer_id( 0 ), + _display_mode(Inkscape::RENDERMODE_NORMAL), + _saved_display_mode(Inkscape::RENDERMODE_NORMAL), _widget( 0 ), _inkscape( 0 ), _guides_message_context( 0 ), @@ -157,6 +168,9 @@ SPDesktop::SPDesktop() : void SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) { + // Temporary workaround for link order issues: + Inkscape::DeviceManager::getManager().getDevices(); + _guides_message_context = new Inkscape::MessageContext(const_cast(messageStack())); current = sp_repr_css_attr_inherited (inkscape_get_repr (INKSCAPE, "desktop"), "style"); @@ -216,6 +230,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) guides = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); sketch = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); controls = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); + tempgroup = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); /* Push select tool to the bottom of stack */ /** \todo @@ -309,11 +324,25 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) layer_manager = new Inkscape::LayerManager( this ); showGrids(namedview->grids_visible, false); + + temporary_item_list = new Inkscape::Display::TemporaryItemList( this ); + snapindicator = new Inkscape::Display::SnapIndicator ( this ); } void SPDesktop::destroy() { + if (snapindicator) { + delete snapindicator; + snapindicator = NULL; + } + if (temporary_item_list) { + delete temporary_item_list; + temporary_item_list = NULL; + } + + namedview->hide(this); + _activate_connection.disconnect(); _deactivate_connection.disconnect(); _sel_modified_connection.disconnect(); @@ -365,30 +394,58 @@ SPDesktop::~SPDesktop() {} //-------------------------------------------------------------------- /* Public methods */ -void SPDesktop::setDisplayModeNormal() + +/* These methods help for temporarily showing things on-canvas. + * The *only* valid use of the TemporaryItem* that you get from add_temporary_canvasitem + * is when you want to prematurely remove the item from the canvas, by calling + * desktop->remove_temporary_canvasitem(tempitem). + */ +/** Note that lifetime is measured in milliseconds + * One should *not* keep a reference to the SPCanvasItem, the temporary item code will + * delete the object for you and the reference will become invalid without you knowing it. + * It is perfectly safe to ignore the returned pointer: the object is deleted by itself, so don't delete it elsewhere! + * The *only* valid use of the returned TemporaryItem* is as argument for SPDesktop::remove_temporary_canvasitem, + * because the object might be deleted already without you knowing it. + * move_to_bottom = true by default so the item does not interfere with handling of other items on the canvas like nodes. + */ +Inkscape::Display::TemporaryItem * +SPDesktop::add_temporary_canvasitem (SPCanvasItem *item, guint lifetime, bool move_to_bottom) { - SP_CANVAS_ARENA (drawing)->arena->rendermode = RENDERMODE_NORMAL; - canvas->rendermode = RENDERMODE_NORMAL; // canvas needs that for choosing the best buffer size - displayMode = RENDERMODE_NORMAL; - sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw - _widget->setTitle(SP_DOCUMENT_NAME(sp_desktop_document(this))); + if (move_to_bottom) { + sp_canvas_item_move_to_z(item, 0); + } + + return temporary_item_list->add_item(item, lifetime); } -void SPDesktop::setDisplayModeOutline() +/** It is perfectly safe to call this function while the object has already been deleted due to a timeout. +*/ +void +SPDesktop::remove_temporary_canvasitem (Inkscape::Display::TemporaryItem * tempitem) { - SP_CANVAS_ARENA (drawing)->arena->rendermode = RENDERMODE_OUTLINE; - canvas->rendermode = RENDERMODE_OUTLINE; // canvas needs that for choosing the best buffer size - displayMode = RENDERMODE_OUTLINE; + // check for non-null temporary_item_list, because during destruction of desktop, some destructor might try to access this list! + if (tempitem && temporary_item_list) { + temporary_item_list->delete_item(tempitem); + } +} + +void SPDesktop::_setDisplayMode(Inkscape::RenderMode mode) { + SP_CANVAS_ARENA (drawing)->arena->rendermode = mode; + canvas->rendermode = mode; + _display_mode = mode; + if (mode != Inkscape::RENDERMODE_OUTLINE) { + _saved_display_mode = _display_mode; + } sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw _widget->setTitle(SP_DOCUMENT_NAME(sp_desktop_document(this))); } -void SPDesktop::displayModeToggle() -{ - if (displayMode == RENDERMODE_OUTLINE) - setDisplayModeNormal(); - else - setDisplayModeOutline(); +void SPDesktop::displayModeToggle() { + if (_display_mode == Inkscape::RENDERMODE_OUTLINE) { + _setDisplayMode(_saved_display_mode); + } else { + _setDisplayMode(Inkscape::RENDERMODE_OUTLINE); + } } /** @@ -419,6 +476,31 @@ void SPDesktop::setCurrentLayer(SPObject *object) { _layer_hierarchy->setBottom(object); } +void SPDesktop::toggleLayerSolo(SPObject *object) { + g_return_if_fail(SP_IS_GROUP(object)); + g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); + + bool othersShowing = false; + std::vector layers; + for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) { + layers.push_back(obj); + othersShowing |= !SP_ITEM(obj)->isHidden(); + } + for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { + layers.push_back(obj); + othersShowing |= !SP_ITEM(obj)->isHidden(); + } + + + if ( SP_ITEM(object)->isHidden() ) { + SP_ITEM(object)->setHidden(false); + } + + for ( std::vector::iterator it = layers.begin(); it != layers.end(); ++it ) { + SP_ITEM(*it)->setHidden(othersShowing); + } +} + /** * Return layer that contains \a object. */ @@ -499,6 +581,15 @@ SPDesktop::change_document (SPDocument *theDocument) selection->clear(); setDocument (theDocument); + + /* update the rulers, connect the desktop widget's signal to the new namedview etc. + (this can probably be done in a better way) */ + Gtk::Window *parent = this->getToplevel(); + g_assert(parent != NULL); + SPDesktopWidget *dtw = (SPDesktopWidget *) parent->get_data("desktopwidget"); + if (dtw) dtw->desktop = this; + sp_desktop_widget_update_namedview(dtw); + _namedview_modified (namedview, SP_OBJECT_MODIFIED_FLAG, this); _document_replaced_signal.emit (this, theDocument); } @@ -643,7 +734,7 @@ SPDesktop::push_current_zoom (GList **history) } /** - * Set viewbox. + * Set viewbox (x0, x1, y0 and y1 are in document pixels. Border is in screen pixels). */ void SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double border, bool log) @@ -671,7 +762,7 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double newscale = viewbox.dimensions()[NR::Y] / (y1 - y0); } - newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); + newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); // unit: 'screen pixels' per 'document pixels' int clear = FALSE; if (!NR_DF_TEST_CLOSE (newscale, scale, 1e-4 * scale)) { @@ -682,13 +773,16 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double clear = TRUE; } - /* Calculate top left corner */ + /* Calculate top left corner (in document pixels) */ x0 = cx - 0.5 * viewbox.dimensions()[NR::X] / newscale; y1 = cy + 0.5 * viewbox.dimensions()[NR::Y] / newscale; /* Scroll */ sp_canvas_scroll_to (canvas, x0 * newscale - border, y1 * -newscale - border, clear); + /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ + sp_box3d_context_update_lines(event_context); + _widget->updateRulers(); _widget->updateScrollbars(expansion(_d2w)); _widget->updateZoom(); @@ -915,6 +1009,16 @@ SPDesktop::zoom_drawing() set_display_area(*d, 10); } +/** + * Scroll canvas by specific coordinate amount in svg coordinates. + */ +void +SPDesktop::scroll_world_in_svg_coords (double dx, double dy, bool is_scrolling) +{ + double scale = expansion(_d2w); + scroll_world(dx*scale, dy*scale, is_scrolling); +} + /** * Scroll canvas by specific coordinate amount. */ @@ -927,6 +1031,9 @@ SPDesktop::scroll_world (double dx, double dy, bool is_scrolling) sp_canvas_scroll_to(canvas, viewbox.min()[NR::X] - dx, viewbox.min()[NR::Y] - dy, FALSE, is_scrolling); + /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ + sp_box3d_context_update_lines(event_context); + _widget->updateRulers(); _widget->updateScrollbars(expansion(_d2w)); } @@ -1086,9 +1193,11 @@ SPDesktop::shutdown() bool SPDesktop::onDeleteUI (GdkEventAny*) { - if(shutdown()) return true; - destroyWidget(); - return false; + if(shutdown()) + return true; + + destroyWidget(); + return false; } /** @@ -1212,6 +1321,12 @@ void SPDesktop::showGrids(bool show, bool dirty_document) } } +void SPDesktop::toggleSnapping() +{ + bool v = namedview->snap_manager.getSnapEnabledGlobally(); + Inkscape::XML::Node *repr = SP_OBJECT_REPR(namedview); + sp_repr_set_boolean(repr, "inkscape:snap-global", !v); +} //---------------------------------------------------------------------- // Callback implementations. The virtual ones are connected by the view. @@ -1529,15 +1644,15 @@ _update_snap_distances (SPDesktop *desktop) //tell all grid snappers for ( GSList const *l = nv.grids; l != NULL; l = l->next) { Inkscape::CanvasGrid *grid = (Inkscape::CanvasGrid*) l->data; - grid->snapper->setDistance(sp_convert_distance_full(nv.gridtolerance, + grid->snapper->setSnapperTolerance(sp_convert_distance_full(nv.gridtolerance, *nv.gridtoleranceunit, px)); } - nv.snap_manager.guide.setDistance(sp_convert_distance_full(nv.guidetolerance, + nv.snap_manager.guide.setSnapperTolerance(sp_convert_distance_full(nv.guidetolerance, *nv.guidetoleranceunit, px)); - nv.snap_manager.object.setDistance(sp_convert_distance_full(nv.objecttolerance, + nv.snap_manager.object.setSnapperTolerance(sp_convert_distance_full(nv.objecttolerance, *nv.objecttoleranceunit, px)); }