/* AbiWord * Copyright (C) 2003 Dom Lachowicz * Copyright (C) 2004 Martin Sevior * * 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 "ut_string.h" #include "ut_assert.h" #include "ut_debugmsg.h" #include "xap_UnixDialogHelper.h" #include "xap_App.h" #include "xap_UnixApp.h" #include "xap_Frame.h" #include "ap_Strings.h" #include "ap_Dialog_Id.h" #include "ap_UnixDialog_Stylist.h" static void s_types_clicked(GtkTreeView *treeview, AP_UnixDialog_Stylist * dlg) { UT_ASSERT(treeview && dlg); GtkTreeSelection * selection; GtkTreeIter iter; GtkTreeModel * model; UT_sint32 row,col; selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(treeview) ); if (!selection || !gtk_tree_selection_get_selected (selection, &model, &iter)) { return; } // Get the row and col number GValue value; memset(&value, 0, sizeof(value)); gtk_tree_model_get_value (model, &iter,1,&value); row = g_value_get_int(&value); g_value_unset (&value); gtk_tree_model_get_value (model, &iter,2,&value); col = g_value_get_int(&value); dlg->styleClicked(row,col); } static gboolean tree_select_filter (GtkTreeSelection * /*selection*/, GtkTreeModel * /*model*/, GtkTreePath *path, gboolean /*path_selected*/, gpointer /*data*/) { if (gtk_tree_path_get_depth (path) > 1) return TRUE; return FALSE; } static void s_types_dblclicked(GtkTreeView *treeview, GtkTreePath * /*arg1*/, GtkTreeViewColumn * /*arg2*/, AP_UnixDialog_Stylist * me) { // simulate the effects of a single click s_types_clicked (treeview, me); me->event_Apply (); } static void s_delete_clicked(GtkWidget * wid, AP_UnixDialog_Stylist * /*me*/ ) { abiDestroyWidget( wid ) ;// will emit signals for us } static void s_destroy_clicked(GtkWidget * /*wid*/, AP_UnixDialog_Stylist * me ) { me->event_Close(); } static void s_response_triggered(GtkWidget * widget, gint resp, AP_UnixDialog_Stylist * dlg) { UT_return_if_fail(widget && dlg); if ( resp == GTK_RESPONSE_APPLY ) dlg->event_Apply(); else if ( resp == GTK_RESPONSE_CLOSE ) abiDestroyWidget(widget); } XAP_Dialog * AP_UnixDialog_Stylist::static_constructor(XAP_DialogFactory * pFactory, XAP_Dialog_Id id) { return new AP_UnixDialog_Stylist(pFactory,id); } AP_UnixDialog_Stylist::AP_UnixDialog_Stylist(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id) : AP_Dialog_Stylist(pDlgFactory,id), m_windowMain(NULL), m_wStyleList(NULL), m_wApply(NULL), m_wClose(NULL), m_wOK(NULL), m_wRenderer(NULL), m_wModel(NULL), m_wStyleListContainer(NULL) { } AP_UnixDialog_Stylist::~AP_UnixDialog_Stylist(void) { } void AP_UnixDialog_Stylist::event_Close(void) { destroy(); } void AP_UnixDialog_Stylist::setStyleInGUI(void) { UT_sint32 row,col; UT_UTF8String sCurStyle = *getCurStyle(); if((getStyleTree() == NULL) || (sCurStyle.size() == 0)) updateDialog(); if(m_wStyleList == NULL) return; if(isStyleTreeChanged()) _fillTree(); getStyleTree()->findStyle(sCurStyle,row,col); UT_DEBUGMSG(("After findStyle row %d col %d col \n",row,col)); UT_UTF8String sPathFull = UT_UTF8String_sprintf("%d:%d",row,col); UT_UTF8String sPathRow = UT_UTF8String_sprintf("%d",row); UT_DEBUGMSG(("Full Path string is %s \n",sPathFull.utf8_str())); GtkTreePath * gPathRow = gtk_tree_path_new_from_string (sPathRow.utf8_str()); GtkTreePath * gPathFull = gtk_tree_path_new_from_string (sPathFull.utf8_str()); gtk_tree_view_expand_row( GTK_TREE_VIEW(m_wStyleList),gPathRow,TRUE); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(m_wStyleList),gPathFull,NULL,TRUE,0.5,0.5); gtk_tree_view_set_cursor(GTK_TREE_VIEW(m_wStyleList),gPathFull,NULL,TRUE); setStyleChanged(false); gtk_tree_path_free(gPathRow); gtk_tree_path_free(gPathFull); } void AP_UnixDialog_Stylist::destroy(void) { finalize(); gtk_widget_destroy(m_windowMain); m_windowMain = NULL; m_wRenderer = NULL; m_wStyleList = NULL; } void AP_UnixDialog_Stylist::activate(void) { UT_ASSERT (m_windowMain); gdk_window_raise (m_windowMain->window); } void AP_UnixDialog_Stylist::notifyActiveFrame(XAP_Frame * /*pFrame*/) { UT_ASSERT(m_windowMain); } /*! * Set the style in the XP layer from the selection in the GUI. */ void AP_UnixDialog_Stylist::styleClicked(UT_sint32 row, UT_sint32 col) { UT_UTF8String sStyle; UT_DEBUGMSG(("row %d col %d clicked \n",row,col)); if((col == 0) && (getStyleTree()->getNumCols(row) == 1)) return; else if(col == 0) getStyleTree()->getStyleAtRowCol(sStyle,row,col); else getStyleTree()->getStyleAtRowCol(sStyle,row,col-1); UT_DEBUGMSG(("StyleClicked row %d col %d style %s \n",row,col,sStyle.utf8_str())); setCurStyle(sStyle); } void AP_UnixDialog_Stylist::runModeless(XAP_Frame * pFrame) { // Build the window's widgets and arrange them GtkWidget * mainWindow = _constructWindow(); UT_return_if_fail(mainWindow); // Populate the window's data items _populateWindowData(); _connectSignals(); abiSetupModelessDialog(GTK_DIALOG(mainWindow),pFrame,this,GTK_RESPONSE_CLOSE); startUpdater(); } void AP_UnixDialog_Stylist::runModal(XAP_Frame * pFrame) { // Build the window's widgets and arrange them m_bIsModal = true; GtkWidget * mainWindow = _constructWindow(); UT_return_if_fail(mainWindow); // Populate the window's data items _populateWindowData(); _connectSignals(); switch (abiRunModalDialog ( GTK_DIALOG(mainWindow), pFrame, this, GTK_RESPONSE_CLOSE,false )) { case GTK_RESPONSE_CLOSE: setStyleValid(false); break; case GTK_RESPONSE_OK: setStyleValid(true); break; default: setStyleValid(false); break; } abiDestroyWidget(mainWindow); } GtkWidget * AP_UnixDialog_Stylist::_constructWindow(void) { // get the path where our UI file is located std::string ui_path; if(m_bIsModal) { ui_path = static_cast(XAP_App::getApp())->getAbiSuiteAppUIDir() + "/ap_UnixDialog_Stylist_modal.xml"; } else { ui_path = static_cast(XAP_App::getApp())->getAbiSuiteAppUIDir() + "/ap_UnixDialog_Stylist.xml"; } // load the dialog from the UI file GtkBuilder* builder = gtk_builder_new(); gtk_builder_add_from_file(builder, ui_path.c_str(), NULL); const XAP_StringSet * pSS = m_pApp->getStringSet (); m_windowMain = GTK_WIDGET(gtk_builder_get_object(builder, "ap_UnixDialog_Stylist")); m_wStyleListContainer = GTK_WIDGET(gtk_builder_get_object(builder, "TreeViewContainer")); if(m_bIsModal) { m_wApply = GTK_WIDGET(gtk_builder_get_object(builder, "btApply")); } else { m_wOK = GTK_WIDGET(gtk_builder_get_object(builder, "btOK")); } m_wClose = GTK_WIDGET(gtk_builder_get_object(builder, "btClose")); // set the dialog title UT_UTF8String s; pSS->getValueUTF8(AP_STRING_ID_DLG_Stylist_Title,s); abiDialogSetTitle(m_windowMain, s.utf8_str()); g_object_unref(G_OBJECT(builder)); return m_windowMain; } void AP_UnixDialog_Stylist::event_Apply(void) { Apply(); } /*! * Fill the GUI tree with the styles as defined in the XP tree. */ void AP_UnixDialog_Stylist::_fillTree(void) { Stylist_tree * pStyleTree = getStyleTree(); if(pStyleTree == NULL) { updateDialog(); pStyleTree = getStyleTree(); } if(pStyleTree->getNumRows() == 0) { updateDialog(); pStyleTree = getStyleTree(); } UT_DEBUGMSG(("Number of rows of styles in document %d \n",pStyleTree->getNumRows())); if(m_wRenderer) { // g_object_unref (G_OBJECT (m_wRenderer)); gtk_widget_destroy (m_wStyleList); } GtkTreeIter iter; GtkTreeIter child_iter; GtkTreeSelection *sel; UT_sint32 row,col, page; m_wModel = gtk_tree_store_new (3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT); page = 0; UT_UTF8String sTmp(""); for(row= 0; row < pStyleTree->getNumRows();row++) { gtk_tree_store_append (m_wModel, &iter, NULL); if(!pStyleTree->getNameOfRow(sTmp,row)) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); break; } if(pStyleTree->getNumCols(row) > 0) { xxx_UT_DEBUGMSG(("Adding Heading %s at row %d \n",sTmp.utf8_str(),row)); gtk_tree_store_set (m_wModel, &iter, 0, sTmp.utf8_str(), 1, row,2,0, -1); for(col =0 ; col < pStyleTree->getNumCols(row); col++) { gtk_tree_store_append (m_wModel, &child_iter, &iter); if(!pStyleTree->getStyleAtRowCol(sTmp,row,col)) { UT_ASSERT(UT_SHOULD_NOT_HAPPEN); break; } gtk_tree_store_set (m_wModel, &child_iter, 0, sTmp.utf8_str(), 1, row,2,col+1, -1); xxx_UT_DEBUGMSG(("Adding style %s at row %d col %d \n",sTmp.utf8_str(),row,col+1)); page++; } } else { xxx_UT_DEBUGMSG(("Adding style %s at row %d \n",sTmp.utf8_str(),row)); gtk_tree_store_set (m_wModel, &iter, 0, sTmp.utf8_str(), 1,row,2,0,-1); page++; } } // create a new treeview m_wStyleList = gtk_tree_view_new_with_model (GTK_TREE_MODEL (m_wModel)); g_object_unref (G_OBJECT (m_wModel)); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (m_wStyleList), true); // get the current selection sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (m_wStyleList)); gtk_tree_selection_set_mode (sel, GTK_SELECTION_BROWSE); gtk_tree_selection_set_select_function (sel, tree_select_filter, NULL, NULL); const XAP_StringSet * pSS = m_pApp->getStringSet (); m_wRenderer = gtk_cell_renderer_text_new (); UT_UTF8String s; pSS->getValueUTF8(AP_STRING_ID_DLG_Stylist_Styles,s); gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (m_wStyleList), -1, s.utf8_str(), m_wRenderer, "text", 0, NULL); gtk_tree_view_collapse_all (GTK_TREE_VIEW (m_wStyleList)); gtk_container_add (GTK_CONTAINER (m_wStyleListContainer), m_wStyleList); g_signal_connect_after(G_OBJECT(m_wStyleList), "cursor-changed", G_CALLBACK(s_types_clicked), static_cast(this)); g_signal_connect_after(G_OBJECT(m_wStyleList), "row-activated", G_CALLBACK(s_types_dblclicked), static_cast(this)); gtk_widget_show_all(m_wStyleList); setStyleTreeChanged(false); } void AP_UnixDialog_Stylist::_populateWindowData(void) { _fillTree(); setStyleInGUI(); } void AP_UnixDialog_Stylist::_connectSignals(void) { g_signal_connect(G_OBJECT(m_windowMain), "response", G_CALLBACK(s_response_triggered), this); // the catch-alls // Dont use gtk_signal_connect_after for modeless dialogs g_signal_connect(G_OBJECT(m_windowMain), "destroy", G_CALLBACK(s_destroy_clicked), (gpointer) this); g_signal_connect(G_OBJECT(m_windowMain), "delete_event", G_CALLBACK(s_delete_clicked), (gpointer) this); }