/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ /* AbiWord * Copyright (C) 1998 AbiSource, Inc. * Copyright (C) Robert Staudinger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ #include #include #include #include "ut_string.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "xap_UnixDialogHelper.h" #include "xap_Dialog_Id.h" #include "xap_UnixApp.h" #include "xap_Frame.h" #include "ap_Strings.h" #include "ap_Dialog_Id.h" #include "ap_Dialog_Goto.h" #include "ap_UnixDialog_Goto.h" /*! * Event dispatcher for spinbutton "page". */ gboolean AP_UnixDialog_Goto__onFocusPage (GtkWidget * /*widget*/, GdkEventFocus *event, gpointer data) { UT_DEBUGMSG (("ROB: _onFocusPage () '%d', '%d'\n", event->type, event->in)); if (event->type == GDK_FOCUS_CHANGE && event->in) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->updateCache (AP_JUMPTARGET_PAGE); } /* propagate further */ return FALSE; } /*! * Event dispatcher for spinbutton "line". */ gboolean AP_UnixDialog_Goto__onFocusLine (GtkWidget * /*widget*/, GdkEventFocus *event, gpointer data) { UT_DEBUGMSG (("ROB: _onFocusLine () '%d', '%d'\n", event->type, event->in)); if (event->type == GDK_FOCUS_CHANGE && event->in) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->updateCache (AP_JUMPTARGET_LINE); } /* propagate further */ return FALSE; } /*! * Event dispatcher for treeview "bookmarks". */ gboolean AP_UnixDialog_Goto__onFocusBookmarks (GtkWidget * /*widget*/, GdkEventFocus *event, gpointer data) { UT_DEBUGMSG (("ROB: _onFocusBookmarks () '%d', '%d'\n", event->type, event->in)); if (event->type == GDK_FOCUS_CHANGE && event->in) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->updateCache (AP_JUMPTARGET_BOOKMARK); } /* propagate further */ return FALSE; } /*! * Event dispatcher for spinbutton "page". */ void AP_UnixDialog_Goto__onPageChanged (GtkSpinButton * /*spinbutton*/, gpointer data) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->onPageChanged (); } /*! * Event dispatcher for spinbutton "line". */ void AP_UnixDialog_Goto__onLineChanged (GtkSpinButton * /*spinbutton*/, gpointer data) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->onLineChanged (); } /*! * Event dispatcher for treeview "bookmarks". */ void AP_UnixDialog_Goto__onBookmarkDblClicked (GtkTreeView * /*tree*/, GtkTreePath * /*path*/, GtkTreeViewColumn * /*col*/, gpointer data) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->onBookmarkDblClicked (); } /*! * Event dispatcher for button "jump". */ void AP_UnixDialog_Goto__onJumpClicked (GtkButton * /*button*/, gpointer data) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->onJumpClicked (); } /*! * Event dispatcher for button "prev". */ void AP_UnixDialog_Goto__onPrevClicked (GtkButton * /*button*/, gpointer data) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->onPrevClicked (); } /*! * Event dispatcher for button "next". */ void AP_UnixDialog_Goto__onNextClicked (GtkButton * /*button*/, gpointer data) { AP_UnixDialog_Goto *dlg = static_cast (data); dlg->onNextClicked (); } /*! * Event dispatcher for button "close". */ void AP_UnixDialog_Goto__onDialogResponse (GtkDialog * /*dialog*/, gint response, gpointer data) { AP_UnixDialog_Goto *dlg = static_cast (data); if (response == GTK_RESPONSE_CLOSE) { dlg->destroy (); } } /*! * Event dispatcher for window. */ gboolean AP_UnixDialog_Goto__onDeleteWindow (GtkWidget * /*widget*/, GdkEvent * /*event*/, gpointer data) { AP_UnixDialog_Goto *dlg = static_cast (data); if (dlg->getWindow ()) { dlg->destroy (); } return TRUE; } /*! * Static ctor. */ XAP_Dialog * AP_UnixDialog_Goto::static_constructor(XAP_DialogFactory *pFactory, XAP_Dialog_Id id) { AP_UnixDialog_Goto *dlg = new AP_UnixDialog_Goto (pFactory, id); return dlg; } /*! * Ctor. */ AP_UnixDialog_Goto::AP_UnixDialog_Goto(XAP_DialogFactory *pDlgFactory, XAP_Dialog_Id id) : AP_Dialog_Goto (pDlgFactory, id), m_wDialog (NULL), m_lbPage (NULL), m_lbLine (NULL), m_lbBookmarks (NULL), m_sbPage (NULL), m_sbLine (NULL), m_lvBookmarks (NULL), m_btJump (NULL), m_btPrev (NULL), m_btNext (NULL), m_btClose (NULL), m_JumpTarget (AP_JUMPTARGET_BOOKMARK) { } /*! * Dtor. */ AP_UnixDialog_Goto::~AP_UnixDialog_Goto () { UT_DEBUGMSG (("ROB: ~AP_UnixDialog_Goto ()\n")); } /*! * Event handler for spinbutton "page". */ void AP_UnixDialog_Goto::onPageChanged () { UT_DEBUGMSG (("ROB: onPageChanged () maxpage='%d'\n", m_DocCount.page)); m_JumpTarget = AP_JUMPTARGET_PAGE; UT_uint32 page = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbPage)); if (page > m_DocCount.page) { gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbPage), 1); } onJumpClicked(); } /*! * Event handler for spinbutton "line". */ void AP_UnixDialog_Goto::onLineChanged () { UT_DEBUGMSG (("ROB: onLineChanged () maxline='%d'\n", m_DocCount.line)); m_JumpTarget = AP_JUMPTARGET_LINE; UT_uint32 line = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbLine)); if (line > m_DocCount.line) { gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), 1); } onJumpClicked(); } /*! * Event handler for treeview "bookmarks". */ void AP_UnixDialog_Goto::onBookmarkDblClicked () { m_JumpTarget = AP_JUMPTARGET_BOOKMARK; onJumpClicked(); } /*! * Event handler for button "jump". */ void AP_UnixDialog_Goto::onJumpClicked () { const gchar *text = NULL; bool freeText = FALSE; switch (m_JumpTarget) { case AP_JUMPTARGET_PAGE: text = gtk_entry_get_text (GTK_ENTRY (m_sbPage)); break; case AP_JUMPTARGET_LINE: text = gtk_entry_get_text (GTK_ENTRY (m_sbLine)); break; case AP_JUMPTARGET_BOOKMARK: text = _getSelectedBookmarkLabel (); freeText = TRUE; break; default: UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::onJumpClicked () no jump target\n")); return; // UT_ASSERT_NOT_REACHED (); } if (!text) return; performGoto(m_JumpTarget, text); if (freeText && text) { g_free ((gchar *)text); } } /*! * Event handler for button "prev". */ void AP_UnixDialog_Goto::onPrevClicked () { UT_DEBUGMSG (("ROB: onPrevClicked () '%d'\n", m_JumpTarget)); UT_uint32 num = 0; switch (m_JumpTarget) { case AP_JUMPTARGET_PAGE: num = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbPage)); if (num == 1) num = m_DocCount.page; else num--; gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbPage), num); break; case AP_JUMPTARGET_LINE: num = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbLine)); if (num == 1) num = m_DocCount.line; else num--; gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), num); break; case AP_JUMPTARGET_BOOKMARK: _selectPrevBookmark (); break; default: UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::onPrevClicked () no jump target\n")); return; // UT_ASSERT_NOT_REACHED (); } onJumpClicked (); } /*! * Event handler for button "next". */ void AP_UnixDialog_Goto::onNextClicked () { UT_DEBUGMSG (("ROB: onNextClicked () '%d'\n", m_JumpTarget)); UT_uint32 num = 0; switch (m_JumpTarget) { case AP_JUMPTARGET_PAGE: num = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbPage)); num++; gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbPage), num); break; case AP_JUMPTARGET_LINE: num = (UT_uint32)gtk_spin_button_get_value (GTK_SPIN_BUTTON (m_sbLine)); num++; gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), num); break; case AP_JUMPTARGET_BOOKMARK: _selectNextBookmark (); break; default: UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::onNextClicked () no jump target\n")); return; // UT_ASSERT_NOT_REACHED (); } onJumpClicked (); } /*! * Set jump target and update cached data like number of lines and pages. * @see ap_types.h */ void AP_UnixDialog_Goto::updateCache (AP_JumpTarget target) { m_JumpTarget = target; updateDocCount (); } /*! * Update cached data like number of lines and pages. */ void AP_UnixDialog_Goto::updateDocCount () { m_DocCount = getView()->countWords (); UT_DEBUGMSG (("ROB: updateCache () page='%d' line='%d'\n", m_DocCount.page, m_DocCount.line)); } /*! * Build dialog. */ void AP_UnixDialog_Goto::constuctWindow (XAP_Frame * /*pFrame*/) { UT_DEBUGMSG (("ROB: constuctWindow ()\n")); // get the path where our UI file is located std::string ui_path = static_cast(XAP_App::getApp())->getAbiSuiteAppUIDir() + "/ap_UnixDialog_Goto.xml"; // load the dialog from the UI file GtkBuilder* builder = gtk_builder_new(); gtk_builder_add_from_file(builder, ui_path.c_str(), NULL); m_wDialog = GTK_WIDGET(gtk_builder_get_object(builder, "ap_UnixDialog_Goto")); m_lbPage = GTK_WIDGET(gtk_builder_get_object(builder, "lbPage")); m_lbLine = GTK_WIDGET(gtk_builder_get_object(builder, "lbLine")); m_lbPage = GTK_WIDGET(gtk_builder_get_object(builder, "lbPage")); m_lbBookmarks = GTK_WIDGET(gtk_builder_get_object(builder, "lbBookmarks")); m_sbPage = GTK_WIDGET(gtk_builder_get_object(builder, "sbPage")); m_sbLine = GTK_WIDGET(gtk_builder_get_object(builder, "sbLine")); m_lvBookmarks = GTK_WIDGET(gtk_builder_get_object(builder, "lvBookmarks")); m_btJump = GTK_WIDGET(gtk_builder_get_object(builder, "btJump")); m_btPrev = GTK_WIDGET(gtk_builder_get_object(builder, "btPrev")); m_btNext = GTK_WIDGET(gtk_builder_get_object(builder, "btNext")); m_btClose = GTK_WIDGET(gtk_builder_get_object(builder, "btClose")); // localise // const XAP_StringSet * pSS = m_pApp->getStringSet (); /* FIXME jump targets localised in xp land, make sure they work for non ascii characters */ const gchar **targets = getJumpTargets (); const gchar *text = NULL; if ((text = targets[AP_JUMPTARGET_PAGE]) != NULL) gtk_label_set_text (GTK_LABEL (m_lbPage), text); if ((text = targets[AP_JUMPTARGET_LINE]) != NULL) gtk_label_set_text (GTK_LABEL (m_lbLine), text); if ((text = targets[AP_JUMPTARGET_BOOKMARK]) != NULL) gtk_label_set_text (GTK_LABEL (m_lbBookmarks), text); // Liststore and -view GtkListStore *store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING); gtk_tree_view_set_model (GTK_TREE_VIEW (m_lvBookmarks), GTK_TREE_MODEL (store)); g_object_unref (G_OBJECT (store)); // Column Bookmark GtkCellRenderer *renderer = NULL; renderer = gtk_cell_renderer_text_new (); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (m_lvBookmarks), -1, "Name", renderer, "text", COLUMN_NAME, NULL); GtkTreeViewColumn *column = gtk_tree_view_get_column (GTK_TREE_VIEW (m_lvBookmarks), 0); gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME); // Signals g_signal_connect (GTK_SPIN_BUTTON (m_sbPage), "focus-in-event", G_CALLBACK (AP_UnixDialog_Goto__onFocusPage), static_cast (this)); g_signal_connect (GTK_SPIN_BUTTON (m_sbPage), "value-changed", G_CALLBACK (AP_UnixDialog_Goto__onPageChanged), static_cast (this)); g_signal_connect (GTK_SPIN_BUTTON (m_sbLine), "focus-in-event", G_CALLBACK (AP_UnixDialog_Goto__onFocusLine), static_cast (this)); g_signal_connect (GTK_SPIN_BUTTON (m_sbLine), "value-changed", G_CALLBACK (AP_UnixDialog_Goto__onLineChanged), static_cast (this)); g_signal_connect (GTK_TREE_VIEW (m_lvBookmarks), "focus-in-event", G_CALLBACK (AP_UnixDialog_Goto__onFocusBookmarks), static_cast (this)); g_signal_connect (GTK_TREE_VIEW (m_lvBookmarks), "row-activated", G_CALLBACK (AP_UnixDialog_Goto__onBookmarkDblClicked), static_cast (this)); g_signal_connect (GTK_BUTTON (m_btJump), "clicked", G_CALLBACK (AP_UnixDialog_Goto__onJumpClicked), static_cast (this)); g_signal_connect (GTK_BUTTON (m_btPrev), "clicked", G_CALLBACK (AP_UnixDialog_Goto__onPrevClicked), static_cast (this)); g_signal_connect (GTK_BUTTON (m_btNext), "clicked", G_CALLBACK (AP_UnixDialog_Goto__onNextClicked), static_cast (this)); g_signal_connect (GTK_DIALOG (m_wDialog), "response", G_CALLBACK (AP_UnixDialog_Goto__onDialogResponse), static_cast (this)); g_signal_connect (m_wDialog, "delete-event", G_CALLBACK (AP_UnixDialog_Goto__onDeleteWindow), static_cast (this)); g_object_unref(G_OBJECT(builder)); } /*! * Update dialog's data. */ void AP_UnixDialog_Goto::updateWindow () { UT_DEBUGMSG (("ROB: updateWindow () #bookmarks='%d', mapped='%d'\n", getExistingBookmarksCount(), GTK_WIDGET_MAPPED(m_wDialog))); ConstructWindowName (); gtk_window_set_title (GTK_WINDOW (m_wDialog), m_WindowName); // pages, page increment of 10 is pretty arbitrary (set in the GtkBuilder UI file) UT_uint32 currentPage = getView()->getCurrentPageNumForStatusBar (); gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbPage), currentPage); // lines, line increment of 10 is pretty arbitrary (set in the GtkBuilder UI file) UT_uint32 currentLine = 1; /* FIXME get current line */ gtk_spin_button_set_value (GTK_SPIN_BUTTON (m_sbLine), currentLine); // bookmarks, detaching model for faster updates GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (m_lvBookmarks)); g_object_ref (G_OBJECT (model)); gtk_tree_view_set_model (GTK_TREE_VIEW (m_lvBookmarks), NULL); gtk_list_store_clear (GTK_LIST_STORE (model)); GtkTreeIter iter; UT_uint32 numBookmarks = getExistingBookmarksCount(); for (UT_uint32 i = 0; i < numBookmarks; i++) { gtk_list_store_append (GTK_LIST_STORE (model), &iter); const gchar *name = getNthExistingBookmark(i); UT_DEBUGMSG ((" ROB: '%s'\n", name)); gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_NAME, name, /* COLUMN_PAGE, "0", COLUMN_NUMBER, 0, */ -1); } gtk_tree_view_set_model (GTK_TREE_VIEW (m_lvBookmarks), model); g_object_unref (G_OBJECT (model)); updateDocCount (); } void AP_UnixDialog_Goto::runModeless (XAP_Frame * pFrame) { UT_DEBUGMSG (("ROB: runModeless ()\n")); constuctWindow (pFrame); UT_ASSERT (m_wDialog); updateWindow (); abiSetupModelessDialog (GTK_DIALOG (m_wDialog), pFrame, this, GTK_RESPONSE_CLOSE); gtk_widget_show_all (m_wDialog); gtk_window_present (GTK_WINDOW (m_wDialog)); } void AP_UnixDialog_Goto::notifyActiveFrame (XAP_Frame * /*pFrame*/) { UT_DEBUGMSG (("ROB: notifyActiveFrame ()\n")); UT_ASSERT (m_wDialog); updateWindow (); /* default to page */ m_JumpTarget = AP_JUMPTARGET_PAGE; } void AP_UnixDialog_Goto::activate (void) { UT_ASSERT (m_wDialog); UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::activate ()\n")); updateWindow (); gtk_window_present (GTK_WINDOW (m_wDialog)); } void AP_UnixDialog_Goto::destroy () { UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::destroy ()\n")); modeless_cleanup (); if (m_wDialog) { gtk_widget_destroy (m_wDialog); m_wDialog = NULL; } } /** * Try to select the bookmark before the current one. * If none is selected the last in the list is picked. * Wraps around. */ void AP_UnixDialog_Goto::_selectPrevBookmark () { UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::_selectPrevBookmark ()\n")); GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (m_lvBookmarks)); UT_return_if_fail (model != NULL); GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (m_lvBookmarks)); GtkTreeIter iter; // try to select prev gboolean haveSelected = gtk_tree_selection_get_selected (selection, &model, &iter); if (haveSelected) { GtkTreePath *path = gtk_tree_model_get_path (model, &iter); gtk_tree_path_prev (path); gboolean havePrev = gtk_tree_model_get_iter (model, &iter, path); if (havePrev) { gtk_tree_selection_select_path (selection, path); gtk_tree_path_free (path); return; } gtk_tree_path_free (path); } // select last UT_uint32 idx = getExistingBookmarksCount () - 1; GtkTreePath *path = gtk_tree_path_new_from_indices (idx); gtk_tree_selection_select_path (selection, path); UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::_selectPrevBookmark () select last '%d'\n", gtk_tree_model_get_iter (model, &iter, path))); gtk_tree_path_free (path); } /** * Try to select the bookmark after the current one. * If none is selected the first in the list is picked. * Wraps around. */ void AP_UnixDialog_Goto::_selectNextBookmark () { UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::_selectNextBookmark ()\n")); GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (m_lvBookmarks)); UT_return_if_fail (model != NULL); GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (m_lvBookmarks)); GtkTreeIter iter; // try to select next gboolean haveSelected = gtk_tree_selection_get_selected (selection, &model, &iter); if (haveSelected) { GtkTreePath *path = gtk_tree_model_get_path (model, &iter); gtk_tree_path_next (path); gboolean haveNext = gtk_tree_model_get_iter (model, &iter, path); if (haveNext) { gtk_tree_selection_select_path (selection, path); gtk_tree_path_free (path); return; } gtk_tree_path_free (path); } // select first GtkTreePath *path = gtk_tree_path_new_first (); gtk_tree_selection_select_path (selection, path); UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::_selectNextBookmark () select first '%d'\n", gtk_tree_model_get_iter (model, &iter, path))); gtk_tree_path_free (path); } /*! * Get the label of the currently selected bookmark in the list. * The returned string has to bee freed. Can return NULL. */ gchar * AP_UnixDialog_Goto::_getSelectedBookmarkLabel () { UT_DEBUGMSG (("ROB: AP_UnixDialog_Goto::_getSelectedBookmarkLabel ()\n")); GtkTreeModel *model = gtk_tree_view_get_model (GTK_TREE_VIEW (m_lvBookmarks)); UT_return_val_if_fail (model != NULL, NULL); GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (m_lvBookmarks)); GtkTreeIter iter; gboolean haveSelected = gtk_tree_selection_get_selected (selection, &model, &iter); if (!haveSelected) return NULL; gchar *label = NULL; gtk_tree_model_get (model, &iter, COLUMN_NAME, &label, -1); return label; }