xml-tree.cpp revision 63c922ae7e6ea7c10d390ed6c570f03f4d09f660
/** @file
* @brief XML editor
*/
/* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* MenTaLguY <mental@rydia.net>
* bulia byak <buliabyak@users.sf.net>
* Johan Engelen <goejendaagh@zonnet.nl>
* David Turner
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
*
* Copyright (C) 1999-2006 Authors
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <gdk/gdkkeysyms.h>
#include "desktop.h"
#include "../desktop-handles.h"
#include "dialog-events.h"
#include "../document.h"
#include "../event-context.h"
#include "../inkscape.h"
#include "../interface.h"
#include "macros.h"
#include "message-context.h"
#include "message-stack.h"
#include "../preferences.h"
#include "../selection.h"
#include "shortcuts.h"
#include "../sp-root.h"
#include "../sp-string.h"
#include "../sp-tspan.h"
#include "ui/icon-names.h"
#include "../verbs.h"
#include "../widgets/sp-xmlview-attr-list.h"
#include "../widgets/sp-xmlview-content.h"
#include "../widgets/sp-xmlview-tree.h"
#include "util/ege-appear-time-tracker.h"
using Inkscape::DocumentUndo;
using ege::AppearTimeTracker;
#define MIN_ONSCREEN_DISTANCE 50
struct EditableDest {
};
// impossible original values to make sure they are read from prefs
static gint selected_attr = 0;
static void sp_xmltree_desktop_activate( Inkscape::Application *inkscape, SPDesktop *desktop, GtkWidget *dialog );
static void sp_xmltree_desktop_deactivate( Inkscape::Application *inkscape, SPDesktop *desktop, GtkWidget *dialog );
static void after_tree_move(GtkCTree *tree, GtkCTreeNode *node, GtkCTreeNode *new_parent, GtkCTreeNode *new_sibling, gpointer data);
static void on_tree_select_row_enable_if_element(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_select_row_enable_if_mutable(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_select_row_show_if_element(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_select_row_show_if_text(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_select_row_enable_if_indentable(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_select_row_enable_if_not_first_child(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_select_row_enable_if_not_last_child(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_select_row_enable_if_has_grandparent(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_unselect_row_clear_text(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_unselect_row_disable(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_tree_unselect_row_hide(GtkCTree *tree, GtkCTreeNode *node, gint column, gpointer data);
static void on_attr_select_row(GtkCList *list, gint row, gint column, GdkEventButton *event, gpointer data);
static void on_attr_unselect_row(GtkCList *list, gint row, gint column, GdkEventButton *event, gpointer data);
static void on_attr_select_row_enable(GtkCList *list, gint row, gint column, GdkEventButton *event, gpointer data);
static void on_attr_unselect_row_disable(GtkCList *list, gint row, gint column, GdkEventButton *event, gpointer data);
static void on_attr_select_row_set_name_content(GtkCList *list, gint row, gint column, GdkEventButton *event, gpointer data);
static void on_attr_select_row_set_value_content(GtkCList *list, gint row, gint column, GdkEventButton *event, gpointer data);
static void on_attr_unselect_row_clear_text(GtkCList *list, gint row, gint column, GdkEventButton *event, gpointer data);
static void _set_status_message(Inkscape::MessageType type, const gchar *message, GtkWidget *dialog);
/*
* \brief Sets the XML status bar when the tree is selected.
*/
void tree_reset_context()
{
_("<b>Click</b> to select nodes, <b>drag</b> to rearrange."));
}
/*
* \brief Sets the XML status bar, depending on which attr is selected.
*/
{
if (attr == 0) {
_("<b>Click</b> attribute to edit."));
}
else {
gchar *message = g_strdup_printf(_("Attribute <b>%s</b> selected. Press <b>Ctrl+Enter</b> when done editing to commit changes."), name);
}
}
void sp_xml_tree_dialog()
{
if (!desktop) {
return;
}
{ // very long block
if (x == -1000 || y == -1000) {
}
if (w ==0 || h == 0) {
}
// if (x<0) x=0;
// if (y<0) y=0;
if (w && h) {
}
if (x >= 0 && y >= 0 && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE))) {
} else {
}
g_signal_connect ( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(sp_transientize_callback), &wd );
paned = gtk_hpaned_new();
);
/* tree view */
_("Drag to reorder nodes") );
/* TODO: replace gtk_signal_connect_while_alive() with something
* else...
*/
toolbar = gtk_toolbar_new();
NULL,
_("New element node"),
NULL,
NULL);
"tree_select_row",
GTK_OBJECT(button));
"tree_unselect_row",
GTK_OBJECT(button));
NULL);
"tree_select_row",
GTK_OBJECT(button));
"tree_unselect_row",
GTK_OBJECT(button));
NULL);
"tree_select_row",
GTK_OBJECT(button));
_("Unindent node"), NULL,
_("Indent node"), NULL,
_("Raise node"), NULL,
_("Lower node"), NULL,
/* node view */
/* attributes */
toolbar = gtk_toolbar_new();
GTK_OBJECT(button));
GTK_OBJECT(button));
GTK_OBJECT(button));
// TRANSLATORS: "Attribute" is a noun here
_("Attribute name") );
set_attr = gtk_button_new();
// TRANSLATORS: "Set" is a verb here
_("Set attribute") );
// TRANSLATORS: "Set" is a verb here
set_attr );
// TRANSLATORS: "Attribute" is a noun here
_("Attribute value") );
attr_value );
attr_value );
attr_value );
GTK_WIDGET(attr_value) );
/* text */
text_container = sw;
} // end of if (dlg == NULL)
if ( wantTiming ) {
// Time tracker takes ownership of the timer.
tracker->setAutodelete(true);
timer = 0;
}
} // end of sp_xml_tree_dialog()
{
SP_SHORTCUT_SHIFT_MASK : 0 ) |
SP_SHORTCUT_CONTROL_MASK : 0 ) |
SP_SHORTCUT_ALT_MASK : 0 );
/* fixme: if you need to add more xml-tree-specific callbacks, you should probably upgrade
* the sp_shortcut mechanism to take into account windows. */
return true;
}
return false;
}
GtkWidget */*dialog*/ )
{
}
SPDesktop */*desktop*/,
GtkWidget */*dialog*/ )
{
}
{
if ( desktop == current_desktop ) {
return;
}
if (current_desktop) {
}
if (desktop) {
sel_changed_connection = sp_desktop_selection(desktop)->connectChanged(&on_desktop_selection_changed);
} else {
}
} // end of set_tree_desktop()
{
if (document == current_document) {
return;
}
if (current_document) {
}
if (current_document) {
document_uri_set_connection = current_document->connectURISet(sigc::bind(sigc::ptr_fun(&on_document_uri_set), current_document));
} else {
}
}
{
if (repr == selected_repr) {
return;
}
if (repr) {
} else {
}
}
{
if (selected_repr) {
}
if (repr) {
if (node) {
while (parent) {
}
}
} else {
}
}
{
} else {
}
if (repr && ( repr->type() == Inkscape::XML::TEXT_NODE || repr->type() == Inkscape::XML::COMMENT_NODE || repr->type() == Inkscape::XML::PI_NODE ) ) {
} else {
}
}
{
if (!current_desktop) {
return NULL;
}
}
{
if (!current_desktop) {
return;
}
if (repr) {
&& sp_repr_parent(repr) )
{
} // end of while loop
} else {
}
blocked++;
&& !(SP_IS_STRING(object) ||
SP_IS_ROOT(object) ) )
{
/* We cannot set selection to root or string - they are not items and selection is not
* equipped to deal with them */
}
blocked--;
} // end of set_dt_select()
gint /*column*/,
gpointer /*data*/)
{
if (blocked) {
return;
}
if (selected_repr == repr) {
return;
}
if (selected_repr) {
}
}
gint /*column*/,
gpointer /*data*/)
{
if (blocked) {
return;
}
selected_attr = 0;
}
}
gpointer /*data*/)
{
{
_("Drag XML subtree"));
} else {
}
}
{
delete _message_context;
}
{
if (x<0) x=0;
if (y<0) y=0;
return FALSE; // which means, go ahead and destroy it
}
static void _set_status_message(Inkscape::MessageType /*type*/, const gchar *message, GtkWidget */*dialog*/)
{
if (status) {
}
}
GtkCTreeNode */*node*/,
gint /*column*/,
{
}
gint /*column*/,
{
} else {
}
}
{
} else {
}
}
{
if ( repr->type() == Inkscape::XML::TEXT_NODE || repr->type() == Inkscape::XML::COMMENT_NODE || repr->type() == Inkscape::XML::PI_NODE ) {
} else {
}
}
{
// top-level is immutable, obviously
return false;
}
// if not in base level (where namedview, defs, etc go), we're mutable
return true;
}
// don't let "defs" or "namedview" disappear
return false;
}
// everyone else is okay, I guess. :)
return true;
}
{
}
{
}
{
}
{
if (GTK_IS_EDITABLE(data)) {
} else if (GTK_IS_TEXT_VIEW(data)) {
}
}
{
}
{
selected_attr = 0;
}
{
if (attr == selected_attr) {
/* if the attr changed, reselect the row in the list to sync
the edit box */
/*
// get current attr values
const gchar * name = g_quark_to_string (sp_xmlview_attr_list_get_row_key (list, row));
const gchar * value = selected_repr->attribute(name);
g_warning("value: '%s'",value);
// get the edit box value
GtkTextIter start, end;
gtk_text_buffer_get_bounds ( gtk_text_view_get_buffer (attr_value),
&start, &end );
gchar * text = gtk_text_buffer_get_text ( gtk_text_view_get_buffer (attr_value),
&start, &end, TRUE );
g_warning("text: '%s'",text);
// compare to edit box
if (strcmp(text,value)) {
// issue warning if they're different
_message_stack->flash(Inkscape::WARNING_MESSAGE,
_("Attribute changed in GUI while editing values!"));
}
g_free (text);
*/
}
}
{
}
GdkEventButton */*event*/,
{
if (!value) {
value = "";
}
}
{
if (xml_tree_node_mutable(node)) {
// skip to the child just before the current repr
indentable = TRUE;
}
}
}
}
gint /*column*/,
{
} else {
}
}
{
} else {
}
}
{
if (parent) {
if (grandparent) {
} else {
}
} else {
}
}
{
}
{
}
{
if (GTK_IS_EDITABLE(data)) {
} else if (GTK_IS_TEXT_VIEW(data)) {
}
}
{
/* TODO: need to do checking a little more rigorous than this */
} else {
}
}
{
if (!blocked++) {
}
blocked--;
}
{
if (current_desktop)
}
{
g_free(t);
}
{
}
{
switch (get_group0_keyval (event)) {
case GDK_Escape: // defocus
return TRUE;
}
return FALSE;
}
{
entry = gtk_entry_new();
sep = gtk_hseparator_new();
bbox = gtk_hbutton_box_new();
create );
gtk_main();
_("Create new element node"));
}
} // end of cmd_new_element_node()
{
_("Create new text node"));
}
{
_("Duplicate node"));
if (node) {
}
}
{
Q_("nodeAsInXMLinHistoryDialog|Delete node"));
}
{
g_assert(selected_attr != 0);
if (updated) {
// force immediate update of dependant attributes
updated->updateRepr();
}
_("Delete attribute"));
}
{
if (updated) {
// force immediate update of dependant attributes
updated->updateRepr();
}
_("Change attribute"));
/* TODO: actually, the row won't have been created yet. why? */
if (row != -1) {
}
}
{
}
_("Raise node"));
}
{
_("Lower node"));
}
{
}
if (prev->firstChild()) {
}
_("Indent node"));
} // end of cmd_indent_node()
{
_("Unindent node"));
} // end of cmd_unindent_node()
/** Returns true iff \a item is suitable to be included in the selection, in particular
whether it has a bounding box in the desktop coordinate system for rendering resize handles.
Descendents of <defs> nodes (markers etc.) return false, for example.
*/
{
/* Definition based on sp_item_i2doc_affine. */
for(;;) {
if (!SP_IS_ITEM(child)) {
return false;
}
break;
}
}
/* Relevance: Otherwise, I'm not sure whether to return true or false. */
return true;
}
/*
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 :