interface.cpp revision 7cbbfa267f06016a7a5865c4132e6eaabef46f49
/**
* @file
* Main UI stuff.
*/
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Frank Felfe <innerspace@iname.com>
* bulia byak <buliabyak@users.sf.net>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
* Kris De Gussem <Kris.DeGussem@gmail.com>
*
* Copyright (C) 2012 Kris De Gussem
* Copyright (C) 2010 authors
* Copyright (C) 1999-2005 authors
* Copyright (C) 2004 David Turner
* Copyright (C) 2001-2002 Ximian, Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "ui/dialog/dialog-manager.h"
#include <gtkmm/icontheme.h>
#include "file.h"
#include <gtkmm/imagemenuitem.h>
#include <gtkmm/separatormenuitem.h>
#include "inkscape.h"
#include "preferences.h"
#include "path-prefix.h"
#include "shortcuts.h"
#include "document.h"
#include "ui/interface.h"
#include "desktop.h"
#include "selection.h"
#include "selection-chemistry.h"
#include "svg-view-widget.h"
#include "widgets/desktop-widget.h"
#include "sp-item-group.h"
#include "sp-text.h"
#include "sp-gradient.h"
#include "sp-flowtext.h"
#include "sp-namedview.h"
#include "sp-root.h"
#include "helper/action-context.h"
#include "helper/gnome-utils.h"
#include "ui/dialog-events.h"
#include "message-context.h"
#include "ui/uxmanager.h"
#include "ui/clipboard.h"
#include "display/sp-canvas.h"
#include "color.h"
#include "svg/svg-color.h"
#include "desktop-style.h"
#include "style.h"
#include "ui/tools/tool-base.h"
#include "gradient-drag.h"
#include "widgets/ege-paint-def.h"
#include "document-undo.h"
#include "sp-anchor.h"
#include "sp-clippath.h"
#include "sp-image.h"
#include "sp-item.h"
#include "sp-mask.h"
#include "message-stack.h"
#include "ui/dialog/layer-properties.h"
#include <gdk/gdkkeysyms.h>
#include <glibmm/miscutils.h>
using Inkscape::DocumentUndo;
/* Drag and Drop */
typedef enum {
static GtkTargetEntry ui_drop_target_entries [] = {
#endif // ENABLE_MAGIC_COLORS
};
static GtkTargetEntry *completeDropTargets = 0;
static int completeDropTargetsCount = 0;
static bool temporarily_block_actions = false;
#define ENTRIES_SIZE(n) sizeof(n)/sizeof(n[0])
static void sp_ui_import_one_file(char const *filename);
static void injectRenamedIcons();
static const int MIN_ONSCREEN_DISTANCE = 50;
void
{
if (editable) {
win->signal_focus_in_event().connect(sigc::mem_fun(*desktop_widget, &SPDesktopWidget::onFocusInEvent));
if (prefs_geometry) {
if (w>0 && h>0) {
x = MIN(gdk_screen_width() - w, x);
y = MIN(gdk_screen_height() - h, y);
desktop->setWindowSize(w, h);
}
// Only restore xy for the first window so subsequent windows don't overlap exactly
// with first. (Maybe rule should be only restore xy if it's different from xy of
// other desktops?)
// Empirically it seems that active_desktop==this desktop only the first time a
// desktop is created.
}
}
if (maxed) {
}
if (full) {
win->fullscreen();
}
}
}
if ( completeDropTargets == 0 || completeDropTargetsCount == 0 )
{
while ( list ) {
int i = 0;
for ( i = 0; typesXX[i]; i++ ) {
}
}
for ( int i = 0; i < (int)nui_drop_target_entries; i++ ) {
}
int pos = nui_drop_target_entries;
pos++;
}
}
"drag_data_received",
NULL);
"drag_motion",
NULL);
"drag_leave",
NULL);
// needed because the first ACTIVATE_DESKTOP was sent when there was no window yet
if ( SP_IS_DESKTOP_WIDGET(vw) ) {
}
}
void
{
if (!document) return;
}
void sp_ui_new_view_preview()
{
if ( document ) {
}
}
void
{
return;
}
return; // Shutdown operation has been canceled, so do nothing
}
// If closing the last document, open a new document so Inkscape doesn't quit.
// Set viewBox if it doesn't exist
doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDisplayUnit()), doc->getHeight().value(doc->getDisplayUnit())));
}
return;
}
// Shutdown can proceed; use the stored reference to the desktop here instead of the current SP_ACTIVE_DESKTOP,
// because the user might have changed the focus in the meantime (see bug #381357 on Launchpad)
dt->destroyWidget();
}
unsigned int
sp_ui_close_all(void)
{
/* Iterate through all the windows, destroying each in the order they
become active */
while (SP_ACTIVE_DESKTOP) {
/* The user canceled the operation, so end doing the close */
return FALSE;
}
// Shutdown can proceed; use the stored reference to the desktop here instead of the current SP_ACTIVE_DESKTOP,
// because the user might have changed the focus in the meantime (see bug #381357 on Launchpad)
dt->destroyWidget();
}
return TRUE;
}
/*
* Some day when the right-click menus are ready to start working
* smarter with the verbs, we'll need to change this NULL being
* sent to sp_action_perform to something useful, or set some kind
* of global "right-clicked position" variable for actions to
* investigate when they're called.
*/
static void
{
if (!temporarily_block_actions) {
}
}
static void
{
}
static void
{
}
static void
{
Inkscape::UI::View::View *view = static_cast<Inkscape::UI::View::View*> (g_object_get_data(G_OBJECT(object), "view"));
}
static void
{
Inkscape::UI::View::View *view = static_cast<Inkscape::UI::View::View*> (g_object_get_data(G_OBJECT(object), "view"));
}
/**
* Creates and attaches a scaled icon to the given menu item.
*/
static void
{
static bool iconsInjected = false;
if ( !iconsInjected ) {
iconsInjected = true;
}
} // end of sp_ui_menu_add_icon
void
{
unsigned int shortcut;
gchar *s;
if (!action)
return;
if (shortcut!=GDK_KEY_VoidSymbol) {
s = g_stpcpy(s, " (");
g_stpcpy(s, ")");
}
}
/**
* Appends a custom menu UI from a verb.
*
* @see ContextMenu::AppendItemFromVerb for a c++ified alternative. Consider dropping sp_ui_menu_append_item_from_verb when c++ifying interface.cpp.
*/
static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb *verb, Inkscape::UI::View::View *view, bool radio = false, GSList *group = NULL)
{
} else {
if (radio) {
} else {
}
item));
item));
}
}
}
return item;
} // end of sp_ui_menu_append_item_from_verb
{
prefPath = "/focus/";
prefPath = "/fullscreen/";
} else {
prefPath = "/window/";
}
return prefPath;
}
static void
{
Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
if (action) {
} else if (pref) {
// All check menu items should have actions now, but just in case
pref_path += "/state";
}
}
{
pref_path += "/state";
}
#if GTK_CHECK_VERSION(3,0,0)
#else
#endif
{
Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
bool ison = false;
if (action) {
}
}
}
else {
}
} else if (pref) {
}
g_signal_handlers_block_by_func(G_OBJECT(menuitem), (gpointer)(GCallback)checkitem_toggled, user_data);
g_signal_handlers_unblock_by_func(G_OBJECT(menuitem), (gpointer)(GCallback)checkitem_toggled, user_data);
return FALSE;
}
{
if ( gtk_check_menu_item_get_active(menuitem) ) {
Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
// note: this will change once more options are in the task set support:
}
}
/**
* Callback function to update the status of the radio buttons in the View -> Display mode menu (Normal, No Filters, Outline) and Color display mode.
*/
#if GTK_CHECK_VERSION(3,0,0)
#else
#endif
{
Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(widget), "view");
bool new_state = false;
} else {
g_warning("update_view_menu does not handle this verb");
}
if (new_state) { //only one of the radio buttons has to be activated; the others will automatically be deactivated
// When the GtkMenuItem version of the "activate" signal has been emitted by a GtkRadioMenuItem, there is a second
// emission as the most recently active item is toggled to inactive. This is dealt with before the original signal is handled.
// This emission however should not invoke any actions, hence we block it here:
temporarily_block_actions = true;
temporarily_block_actions = false;
}
}
return FALSE;
}
static void
sp_ui_menu_append_check_item_from_verb(GtkMenu *menu, Inkscape::UI::View::View *view, gchar const *label, gchar const *tip, gchar const *pref,
#if GTK_CHECK_VERSION(3,0,0)
#else
#endif
{
#if 0
}
#endif
#if GTK_CHECK_VERSION(3,0,0)
#else
#endif
g_signal_connect( G_OBJECT(item), "select", G_CALLBACK(sp_ui_menu_select), (gpointer) (action ? action->tip : tip));
}
static void
{
// dealing with the bizarre filename convention in Inkscape for now
}
static void
{
//sp_ui_menu_append_check_item_from_verb(m, view, _("_Menu"), _("Show or hide the menu bar"), "menu",
// checkitem_toggled, checkitem_update, 0);
}
{
0, 0
};
int count = 0;
gint active = Inkscape::UI::UXManager::getInstance()->getDefaultTask( dynamic_cast<SPDesktop*>(view) );
{
{
}
g_signal_connect( G_OBJECT(item), "toggled", reinterpret_cast<GCallback>(taskToggled), GINT_TO_POINTER(count) );
g_signal_connect( G_OBJECT(item), "select", G_CALLBACK(sp_ui_menu_select), const_cast<gchar*>(strs[1]) );
gtk_widget_show( item );
}
}
/**
* Observer that updates the recent list's max document count.
*/
public:
{}
// hack: the recent menu doesn't repopulate after changing the limit, so we force it
}
private:
};
/**
* This function turns XML into a menu.
*
* This function is realitively simple as it just goes through the XML
* and parses the individual elements. In the case of a submenu, it
* just calls itself recursively. Because it is only reasonable to have
* a couple of submenus, it is unlikely this will go more than two or
* three times.
*
* In the case of an unrecognized verb, a menu item is made to identify
* the verb that is missing, and display that. The menu item is also made
* insensitive.
*
* @param menus This is the XML that defines the menu
* @param menu Menu to be added to
* @param view The View that this menu is being built for
*/
static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, Inkscape::UI::View::View *view)
{
continue;
}
}
#if GTK_CHECK_VERSION(3,0,0)
#else
#endif
}
}
} else {
}
} else {
gtk_widget_set_sensitive(item, false);
}
continue;
}
continue;
}
// create recent files menu
// sort most recently used documents first to preserve previous behavior
g_signal_connect(G_OBJECT(recent_menu), "item-activated", G_CALLBACK(sp_recent_open), (gpointer) NULL);
// add filter to only open files added by Inkscape
// this will just sit and update the list's item count
continue;
}
continue;
}
continue;
}
}
}
{
return mbar;
}
/* Drag and Drop */
void
guint /*event_time*/,
gpointer /*user_data*/)
{
switch (info) {
case APP_X_INKY_COLOR:
{
int destX = 0;
int destY = 0;
if ( item )
{
gchar c[64] = {0};
// Careful about endian issues.
sp_svg_write_color( c, sizeof(c),
0xff // can't have transparency in the color itself
//0x0ff & (data->data[3] >> 8),
));
bool updatePerformed = false;
// piggie-backed palette entry info
for ( int i = 0; i < dataVals[6]; i++ ) {
}
// Now hook in a magic tag of some sort.
str = 0;
false );
item->updateRepr();
updatePerformed = true;
}
}
if ( !updatePerformed ) {
}
item->updateRepr();
_("Drop color"));
if ( srgbProf ) {
}
}
}
}
break;
#endif // ENABLE_MAGIC_COLORS
case APP_X_COLOR:
{
int destX = 0;
int destY = 0;
// Careful about endian issues.
0xff // can't have transparency in the color itself
//0x0ff & (data->data[3] >> 8),
));
bool consumed = false;
if (consumed) {
}
}
//if (!consumed && tools_active(desktop, TOOLS_TEXT)) {
// consumed = sp_text_context_drop_color(c, button_doc);
// if (consumed) {
// SPDocumentUndo::done( doc , SP_VERB_NONE, _("Drop color on gradient stop"));
// }
//}
if (fillnotstroke &&
boost::optional<Path::cut_position> position = get_nearest_position_on_Path(livarot_path, button_doc);
if (position) {
double stroke_tolerance =
desktop->current_zoom() *
: 0.0)
fillnotstroke = false;
}
}
delete livarot_path;
}
item->updateRepr();
_("Drop color") );
}
}
}
break;
case APP_OSWB_COLOR:
{
bool worked = false;
reinterpret_cast<char const *>(gtk_selection_data_get_data (data)),
if ( worked ) {
colorspec = "none";
} else {
SPGradient* matches = 0;
break;
}
}
}
if (matches) {
colorspec = "url(#";
colorspec += ")";
} else {
}
}
}
}
if ( worked ) {
int destX = 0;
int destY = 0;
bool consumed = false;
if (consumed) {
}
}
if (fillnotstroke &&
boost::optional<Path::cut_position> position = get_nearest_position_on_Path(livarot_path, button_doc);
if (position) {
double stroke_tolerance =
desktop->current_zoom() *
: 0.0)
fillnotstroke = false;
}
}
delete livarot_path;
}
item->updateRepr();
_("Drop color") );
}
}
}
break;
case SVG_DATA:
case SVG_XML_DATA: {
Inkscape::XML::Document *rnewdoc = sp_repr_read_mem(svgdata, gtk_selection_data_get_length (data), SP_SVG_NS_URI);
sp_ui_error_dialog(_("Could not parse SVG data"));
return;
}
}
// Add it to the current layer
// Greg's edits to add intelligent positioning of svg drops
// move to mouse pointer
{
if (sel_bbox) {
sp_selection_move_relative(selection, m, false);
}
}
_("Drop SVG") );
break;
}
case URI_LIST: {
break;
}
case APP_X_INK_PASTE: {
break;
}
case PNG_DATA:
case JPEG_DATA:
case IMAGE_DATA: {
++i;
}
NULL);
_("Drop bitmap image") );
break;
}
}
}
#include "ui/tools/gradient-tool.h"
GdkDragContext */*drag_context*/,
GtkSelectionData */*data*/,
guint /*info*/,
guint /*event_time*/,
gpointer /*user_data*/)
{
// SPDocument *doc = SP_ACTIVE_DOCUMENT;
// SPDesktop *desktop = SP_ACTIVE_DESKTOP;
// g_message("drag-n-drop motion (%4d, %4d) at %d", x, y, event_time);
}
GdkDragContext */*drag_context*/,
guint /*event_time*/,
gpointer /*user_data*/ )
{
// g_message("drag-n-drop leave at %d", event_time);
}
static void
{
if (!list)
return;
}
static void
{
if (filename) {
sp_ui_import_one_file((char const *)filename);
}
}
static void
sp_ui_import_one_file(char const *filename)
{
if (!doc) return;
// Pass off to common implementation
// TODO might need to get the proper type of Inkscape::Extension::Extension
}
void
{
}
bool
{
bool return_value = FALSE;
_( "<span weight=\"bold\" size=\"larger\">A file named \"%s\" already exists. Do you want to replace it?</span>\n\n"
"The file already exists in \"%s\". Replacing it will overwrite its contents." ),
);
_("_Cancel"), GTK_RESPONSE_NO,
_("Replace"), GTK_RESPONSE_YES,
NULL );
return_value = TRUE;
} else {
}
} else {
return_value = TRUE;
}
return return_value;
}
static void
{
//child is either
//- a GtkBox, whose first child is a label displaying name if the menu
//item has an accel key
//- a GtkLabel if the menu has no accel key
if (GTK_IS_LABEL(child)) {
} else if (GTK_IS_BOX(child)) {
}//else sp_ui_menu_append_item_from_verb has been modified and can set
//a menu item in yet another way...
}
}
}
void injectRenamedIcons()
{
for ( std::vector< std::pair<Glib::ustring, Glib::ustring> >::iterator it = renamed.begin(); it < renamed.end(); ++it ) {
if ( !hasIcon && hasSecondIcon ) {
if ( pb ) {
// install a private copy of the pixbuf to avoid pinning a theme
}
}
}
}
}
MIGroup(),
MIParent(_("Go to parent"))
{
// g_message("ContextMenu");
AddSeparator();
AddSeparator();
positionOfLastDialog = 10; // 9 in front + 1 for the separator in the next if; used to position the dialog menu entries below each other
/* Item menu */
AddSeparator();
}
/* layer menu */
if (item) {
if (SP_IS_GROUP(item)) {
}
}
( _desktop->currentLayer() != _desktop->currentRoot() && _desktop->currentLayer()->parent != _desktop->currentRoot() ) ) {
AddSeparator();
}
/* TRANSLATORS: #%1 is the id of the group e.g. <g id="#g7">, not a number. */
MIGroup.signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &ContextMenu::EnterGroup),&MIGroup));
}
}
}
}
ContextMenu::~ContextMenu(void)
{
}
{
return sep;
}
{
}
void ContextMenu::LeaveGroup(void)
{
}
void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb)//, SPDesktop *view)//, bool radio, GSList *group)
{
} else {
if (!action) {
return;
}
}
}
}
}
void ContextMenu::MakeObjectMenu(void)
{
// GObjectClass *klass = G_OBJECT_GET_CLASS(_object); //to deduce the object's type from its class
//
// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_ITEM))
// {
// MakeItemMenu ();
// }
// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_GROUP))
// {
// MakeGroupMenu();
// }
// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_ANCHOR))
// {
// MakeAnchorMenu();
// }
// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_IMAGE))
// {
// MakeImageMenu();
// }
// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_SHAPE))
// {
// MakeShapeMenu();
// }
// if (G_TYPE_CHECK_CLASS_TYPE(klass, SP_TYPE_TEXT))
// {
// MakeTextMenu();
// }
if (SP_IS_ITEM(_object)) {
MakeItemMenu();
}
if (SP_IS_GROUP(_object)) {
}
if (SP_IS_ANCHOR(_object)) {
}
if (SP_IS_IMAGE(_object)) {
}
if (SP_IS_SHAPE(_object)) {
}
if (SP_IS_TEXT(_object)) {
MakeTextMenu();
}
}
void ContextMenu::MakeItemMenu (void)
{
/* Item dialog */
AddSeparator();
/* Select item */
} else {
}
}
}
/* Select same fill and stroke */
/* Select same fill color */
/* Select same stroke color */
/* Select same stroke style */
/* Select same stroke style */
/* Move to layer */
} else {
}
/* Create link */
bool ClipRefOK=false;
bool MaskRefOK=false;
if (_item){
ClipRefOK=true;
}
}
}
if (_item){
MaskRefOK=true;
}
}
}
/* Set mask */
} else {
}
/* Release mask */
if (MaskRefOK) {
} else {
}
/*SSet Clip Group */
/* Set Clip */
} else {
}
/* Release Clip */
if (ClipRefOK) {
} else {
}
/* Group */
} else {
}
}
void ContextMenu::SelectSameFillStroke(void)
{
sp_select_same_fill_stroke_style(_desktop, true, true, true);
}
void ContextMenu::SelectSameFillColor(void)
{
sp_select_same_fill_stroke_style(_desktop, true, false, false);
}
void ContextMenu::SelectSameStrokeColor(void)
{
sp_select_same_fill_stroke_style(_desktop, false, true, false);
}
void ContextMenu::SelectSameStrokeStyle(void)
{
sp_select_same_fill_stroke_style(_desktop, false, false, true);
}
void ContextMenu::SelectSameObjectType(void)
{
}
void ContextMenu::ItemProperties(void)
{
}
void ContextMenu::ItemSelectThis(void)
{
}
void ContextMenu::ItemMoveTo(void)
{
}
void ContextMenu::ItemCreateLink(void)
{
_item->deleteObject(false);
}
void ContextMenu::SetMask(void)
{
sp_selection_set_mask(_desktop, false, false);
}
void ContextMenu::ReleaseMask(void)
{
sp_selection_unset_mask(_desktop, false);
}
void ContextMenu::CreateGroupClip(void)
{
}
void ContextMenu::SetClip(void)
{
sp_selection_set_mask(_desktop, true, false);
}
void ContextMenu::ReleaseClip(void)
{
sp_selection_unset_mask(_desktop, true);
}
void ContextMenu::MakeGroupMenu(void)
{
/* Ungroup */
}
void ContextMenu::ActivateGroup(void)
{
}
void ContextMenu::ActivateUngroup(void)
{
}
void ContextMenu::MakeAnchorMenu(void)
{
/* Link dialog */
/* Select item */
/* Reset transformations */
}
void ContextMenu::AnchorLinkProperties(void)
{
}
void ContextMenu::AnchorLinkFollow(void)
{
}
// Opening the selected links with a python extension
if (verb) {
if (action) {
}
}
}
void ContextMenu::AnchorLinkRemove(void)
{
}
void ContextMenu::MakeImageMenu (void)
{
/* Image properties */
/* Edit externally */
}
/* Trace Bitmap */
}
/* Trace Pixel Art */
}
/* Embed image */
}
}
/* Extract image */
}
}
}
void ContextMenu::ImageProperties(void)
{
}
}
else {
value = "gimp";
}
return value;
}
void ContextMenu::ImageEdit(void)
{
}
#ifdef WIN32
// g_spawn_command_line_sync parsing is done according to Unix shell rules,
// not Windows command interpreter rules. Thus we need to enclose the
// executable path with single quotes.
if ( index >= 0 ) {
} else {
// Enclose the whole command line if no executable path can be extracted.
}
#endif
// URI to filename conversion
} else {
}
} else if (SP_ACTIVE_DOCUMENT->getBase()) {
} else {
}
}
//g_warning("##Command line: %s\n", cmdline.c_str());
if ( errThing ) {
errThing = 0;
}
}
void ContextMenu::ImageTraceBitmap(void)
{
}
void ContextMenu::ImageTracePixelArt(void)
{
}
void ContextMenu::ImageEmbed(void)
{
}
if (verb) {
if (action) {
}
}
}
void ContextMenu::ImageExtract(void)
{
}
if (verb) {
if (action) {
}
}
}
void ContextMenu::MakeShapeMenu (void)
{
/* Item dialog */
}
void ContextMenu::FillSettings(void)
{
}
}
void ContextMenu::MakeTextMenu (void)
{
/* Fill and Stroke dialog */
/* Edit Text dialog */
/* Spellcheck dialog */
}
void ContextMenu::TextSettings (void)
{
}
}
void ContextMenu::SpellcheckSettings (void)
{
}
}
/*
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 :