/* * Copyright (C) 2004 Luca Padovani * Copyright (C) 2005 Martin Sevior * Copyright (C) 2005 Jean Brefort * * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 * USA */ #ifdef ABI_PLUGIN_BUILTIN #define abi_plugin_register abipgn_abigochart_register #define abi_plugin_unregister abipgn_abigochart_unregister #define abi_plugin_supports_version abipgn_abigochart_supports_version #endif #include "xap_Module.h" #include "ie_imp_GOChart.h" #include "ie_imp_GOComponent.h" #include "xap_App.h" #include "xap_Frame.h" #include "ap_Menu_Id.h" #include "ev_Menu_Actions.h" #include "ev_EditMethod.h" #include "xap_Menu_Layouts.h" #include "ut_stack.h" #include "AbiGOffice.h" #include "AbiGOChart.h" #include "AbiGOComponent.h" #include #include // // GOCmdContext interface implementation for AbiGOffice // // we must implement it at least for errors reporting typedef GObject AbiCmdContext; typedef GObjectClass AbiCmdContextClass; static void abi_error_error (G_GNUC_UNUSED GOCmdContext *cc, GError *error) { fprintf (stderr, "Error: %s\n", error->message); } static void abi_error_info (G_GNUC_UNUSED GOCmdContext *cc, GOErrorInfo *error) { go_error_info_print (error); } static char * abi_get_password (G_GNUC_UNUSED GOCmdContext *cc, G_GNUC_UNUSED char const* filename) { return NULL; } static void abi_set_sensitive (G_GNUC_UNUSED GOCmdContext *cc, G_GNUC_UNUSED gboolean sensitive) { } static void abi_progress_set (G_GNUC_UNUSED GOCmdContext *cc, G_GNUC_UNUSED double val) { } static void abi_progress_message_set (G_GNUC_UNUSED GOCmdContext *cc, G_GNUC_UNUSED gchar const *msg) { } static void abi_cmd_context_init (GOCmdContextClass *iface) { iface->get_password = abi_get_password; iface->set_sensitive = abi_set_sensitive; iface->error.error = abi_error_error; iface->error.error_info = abi_error_info; iface->progress_set = abi_progress_set; iface->progress_message_set = abi_progress_message_set; } GSF_CLASS_FULL (AbiCmdContext, abi_cmd_context, NULL, NULL, NULL, NULL, NULL, G_TYPE_OBJECT, 0, GSF_INTERFACE (abi_cmd_context_init, GO_TYPE_CMD_CONTEXT)) // // AbiGOffice_addToMenus // ----------------------- // Adds "Object" "Gnome Office Chart" "FromFile" options to AbiWord's Main Menu. // // FIXME make these translatable strings static const char * Object_MenuLabelObject = "Object"; static const char * Object_MenuTooltipObject = "Insert Embeddable Object"; static const char* AbiGOChart_MenuLabelInsert = "Gnome Office Chart"; static const char* AbiGOChart_MenuTooltipInsert = "Create a chart"; static const char* AbiGOComponent_MenuLabelInsertFromFile = "From File"; static const char* AbiGOComponent_MenuTooltipInsertFromFile = "Insert the contents of a file"; static const char* AbiGOComponent_MenuLabelCreate = "New"; static const char* AbiGOComponent_MenuTooltipCreate = "Create a new object"; static XAP_Menu_Id newObjectID = 0; static XAP_Menu_Id InsertGOChartID = 0; static XAP_Menu_Id InsertGOComponentFromFileID = 0; static XAP_Menu_Id CreateGOComponentID = 0; static void AbiGOffice_addToMenus() { // First we need to get a pointer to the application itself. XAP_App *pApp = XAP_App::getApp(); // // Translated Strings // // const XAP_StringSet * pSS = pApp->getStringSet(); // AbiMathView_MenuLabelEquation= pSS->getValue(AP_STRING_ID_MENU_LABEL_INSERT_EQUATION); // AbiMathView_MenuTooltipEquation = pSS->getValue(AP_STRING_ID_MENU_LABEL_TOOLTIP_INSERT_EQUATION); // AbiMathView_MenuLabelFileInsert = pSS->getValue(AP_STRING_ID_MENU_LABEL_INSERT_EQUATION_FILE); // AbiMathView_MenuTooltipFileInsert = pSS->getValue(AP_STRING_ID_MENU_LABEL_TOOLTIP_INSERT_EQUATION_FILE); // Create an EditMethod that will link our method's name with // it's callback function. This is used to link the name to // the callback. EV_EditMethod *myEditMethodFile = new EV_EditMethod( "AbiGOChart_Create", // name of callback function AbiGOChart_Create, // callback function itself. 0, // no additional data required. "" // description -- allegedly never used for anything ); // Now we need to get the EditMethod container for the application. // This holds a series of Edit Methods and links names to callbacks. EV_EditMethodContainer* pEMC = pApp->getEditMethodContainer(); // We have to add our EditMethod to the application's EditMethodList // so that the application will know what callback to call when a call // to "AbiMathView_FileInsert" is received. pEMC->addEditMethod(myEditMethodFile); // Now we need to grab an ActionSet. This is going to be used later // on in our for loop. Take a look near the bottom. EV_Menu_ActionSet* pActionSet = pApp->getMenuActionSet(); XAP_Menu_Factory * pFact = pApp->getMenuFactory(); // Look to see if "Object" has been loaded already.. bool bObjectExists = true; if(newObjectID <= 0) { // Put it after Insert Picture in the Main menu // FIXME put it before! bObjectExists = false; newObjectID= pFact->addNewMenuBefore("Main",NULL,AP_MENU_ID_INSERT_DIRECTIONMARKER,EV_MLF_BeginSubMenu); } UT_DEBUGMSG(("newObjectID %d \n",newObjectID)); pFact->addNewLabel(NULL,newObjectID,Object_MenuLabelObject, Object_MenuTooltipObject); // Create the Action that will be called. EV_Menu_Action* myObjectAction = new EV_Menu_Action( newObjectID, // id that the layout said we could use 1, // yes, we have a sub menu. 0, // no, we don't raise a dialog. 0, // no, we don't have a checkbox. 0, // no radio buttons for me, thank you NULL, // no callback function to call. NULL, // don't know/care what this is for NULL // don't know/care what this is for ); // Now what we need to do is add this particular action to the ActionSet // of the application. This forms the link between our new ID that we // got for this particular frame with the EditMethod that knows how to // call our callback function. pActionSet->addAction(myObjectAction); InsertGOChartID= pFact->addNewMenuAfter("Main",NULL,newObjectID,EV_MLF_Normal); UT_DEBUGMSG(("GOChart ID %d \n",InsertGOChartID)); pFact->addNewLabel(NULL, InsertGOChartID,AbiGOChart_MenuLabelInsert, AbiGOChart_MenuTooltipInsert); // Create the Action that will be called. EV_Menu_Action* myChartAction = new EV_Menu_Action( InsertGOChartID, // id that the layout said we could use 0, // no, we don't have a sub menu. 1, // yes, we raise a dialog. 0, // no, we don't have a checkbox. 0, // no radio buttons for me, thank you "AbiGOChart_Create", // name of callback function to call. NULL, // don't know/care what this is for NULL // don't know/care what this is for ); // Now what we need to do is add this particular action to the ActionSet // of the application. This forms the link between our new ID that we // got for this particular frame with the EditMethod that knows how to // call our callback function. pActionSet->addAction(myChartAction); if (g_slist_length (mime_types) > 0) { myEditMethodFile = new EV_EditMethod( "AbiGOComponent_FileInsert", // name of callback function AbiGOComponent_FileInsert, // callback function itself. 0, // no additional data required. "" // description -- allegedly never used for anything ); pEMC->addEditMethod(myEditMethodFile); myEditMethodFile = new EV_EditMethod( "AbiGOComponent_Create", // name of callback function AbiGOComponent_Create, // callback function itself. 0, // no additional data required. "" // description -- allegedly never used for anything ); pEMC->addEditMethod(myEditMethodFile); InsertGOComponentFromFileID= pFact->addNewMenuAfter("Main",NULL,InsertGOChartID,EV_MLF_Normal); UT_DEBUGMSG(("GOComponentFromFile ID %d \n",InsertGOComponentFromFileID)); pFact->addNewLabel(NULL, InsertGOComponentFromFileID,AbiGOComponent_MenuLabelInsertFromFile, AbiGOComponent_MenuTooltipInsertFromFile); // Create the Action that will be called. EV_Menu_Action* myFileAction = new EV_Menu_Action( InsertGOComponentFromFileID, // id that the layout said we could use 0, // no, we don't have a sub menu. 1, // yes, we raise a dialog. 0, // no, we don't have a checkbox. 0, // no radio buttons for me, thank you "AbiGOComponent_FileInsert", // name of callback function to call. NULL, // don't know/care what this is for NULL // don't know/care what this is for ); // Now what we need to do is add this particular action to the ActionSet // of the application. This forms the link between our new ID that we // got for this particular frame with the EditMethod that knows how to // call our callback function. pActionSet->addAction(myFileAction); CreateGOComponentID= pFact->addNewMenuAfter("Main",NULL,InsertGOComponentFromFileID,EV_MLF_Normal); UT_DEBUGMSG(("CreateGOComponent ID %d \n",CreateGOComponentID)); pFact->addNewLabel(NULL, CreateGOComponentID,AbiGOComponent_MenuLabelCreate, AbiGOComponent_MenuTooltipCreate); // Create the Action that will be called. EV_Menu_Action* myCompAction = new EV_Menu_Action( CreateGOComponentID, // id that the layout said we could use 0, // no, we don't have a sub menu. 1, // yes, we raise a dialog. 0, // no, we don't have a checkbox. 0, // no radio buttons for me, thank you "AbiGOComponent_Create", // name of callback function to call. NULL, // don't know/care what this is for NULL // don't know/care what this is for ); // Now what we need to do is add this particular action to the ActionSet // of the application. This forms the link between our new ID that we // got for this particular frame with the EditMethod that knows how to // call our callback function. pActionSet->addAction(myCompAction); if(!bObjectExists) { XAP_Menu_Id endObjectID= pFact->addNewMenuAfter("Main",NULL,CreateGOComponentID,EV_MLF_EndSubMenu); UT_DEBUGMSG(("End Object ID %d \n",endObjectID)); pFact->addNewLabel(NULL,endObjectID,NULL,NULL); // Create the Action that will be called. EV_Menu_Action* myEndObjectAction = new EV_Menu_Action( endObjectID, // id that the layout said we could use 0, // no, we don't have a sub menu. 0, // no, we raise a dialog. 0, // no, we don't have a checkbox. 0, // no radio buttons for me, thank you NULL, // name of callback function to call. NULL, // don't know/care what this is for NULL // don't know/care what this is for ); pActionSet->addAction(myEndObjectAction); } } else if(!bObjectExists) { XAP_Menu_Id endObjectID= pFact->addNewMenuAfter("Main",NULL,InsertGOChartID,EV_MLF_EndSubMenu); UT_DEBUGMSG(("End Object ID %d \n",endObjectID)); pFact->addNewLabel(NULL,endObjectID,NULL,NULL); // Create the Action that will be called. EV_Menu_Action* myEndObjectAction = new EV_Menu_Action( endObjectID, // id that the layout said we could use 0, // no, we don't have a sub menu. 0, // no, we raise a dialog. 0, // no, we don't have a checkbox. 0, // no radio buttons for me, thank you NULL, // name of callback function to call. NULL, // don't know/care what this is for NULL // don't know/care what this is for ); pActionSet->addAction(myEndObjectAction); } // We need to go through and add the menu element to each "frame" // of the application. We can iterate through the frames by doing // XAP_App::getFrameCount() to tell us how many frames there are, // then calling XAP_App::getFrame(i) to get the i-th frame. int frameCount = pApp->getFrameCount(); for(int i = 0;i < frameCount;++i) { // Get the current frame that we're iterating through. XAP_Frame* pFrame = pApp->getFrame(i); pFrame->rebuildMenus(); } } static void AbiGOffice_removeFromMenus () { // First we need to get a pointer to the application itself. XAP_App *pApp = XAP_App::getApp(); XAP_Menu_Factory * pFact = pApp->getMenuFactory(); // remove the edit method EV_EditMethodContainer* pEMC = pApp->getEditMethodContainer() ; EV_EditMethod * pEM = ev_EditMethod_lookup ( "AbiGOChart_Create" ) ; pEMC->removeEditMethod ( pEM ) ; DELETEP( pEM ) ; pFact->removeMenuItem("Main",NULL,InsertGOChartID); if (g_slist_length (mime_types) > 0) { pEM = ev_EditMethod_lookup ( "AbiGOComponent_FileInsert" ) ; pEMC->removeEditMethod ( pEM ) ; DELETEP( pEM ) ; pEM = ev_EditMethod_lookup ( "AbiGOComponent_Create" ) ; pEMC->removeEditMethod ( pEM ) ; DELETEP( pEM ) ; pFact->removeMenuItem("Main",NULL,InsertGOComponentFromFileID); pFact->removeMenuItem("Main",NULL,CreateGOComponentID); } pFact->removeMenuItem("Main",NULL,newObjectID); int frameCount = pApp->getFrameCount(); for(int i = 0;i < frameCount;++i) { // Get the current frame that we're iterating through. XAP_Frame* pFrame = pApp->getFrame(i); pFrame->rebuildMenus(); } } static UT_uint32 GOChartManagerUID = 0; static GR_GOChartManager *pGOChartManager = NULL; UT_Stack ComponentManagers; typedef struct { UT_uint32 UID; GR_GOComponentManager *Manager; } ManagerStruct; static void create_manager_cb (char const *mime_type, XAP_App * pApp) { ManagerStruct *s = new ManagerStruct; s->Manager = new GR_GOComponentManager(NULL, mime_type); s->UID = pApp->registerEmbeddable(s->Manager); ComponentManagers.push (s); if (go_components_support_clipboard (mime_type)) pApp->addClipboardFmt (mime_type); UT_DEBUGMSG(("Class %x created for %s!\n", s->UID, go_mime_type_get_description (mime_type))); } static IE_Imp_Object_Sniffer * m_impSniffer = 0; static IE_Imp_Component_Sniffer * m_impCSniffer = 0; static GOCmdContext *cc; GOCmdContext * abi_goffice_get_cmd_context (void) { return cc; } ABI_PLUGIN_DECLARE(AbiGOChart) // ----------------------------------------------------------------------- // // Abiword Plugin Interface // // ----------------------------------------------------------------------- ABI_FAR_CALL int abi_plugin_register (XAP_ModuleInfo * mi) { mi->name = "AbiGOffice"; mi->desc = "The plugin enables Gnome Office Charts and components to be displayed in AbiWord"; mi->version = ABI_VERSION_STRING; mi->author = "Jean Bréfort "; mi->usage = "No Usage"; // Add to AbiWord's plugin importers m_impSniffer = new IE_Imp_Object_Sniffer(); IE_Imp::registerImporter (m_impSniffer); m_impCSniffer = new IE_Imp_Component_Sniffer(); IE_Imp::registerImporter (m_impCSniffer); // Add to AbiWord's plugin listeners XAP_App * pApp = XAP_App::getApp(); pGOChartManager = new GR_GOChartManager(NULL); pGOChartManager->buildContextualMenu (); GOChartManagerUID = pApp->registerEmbeddable(pGOChartManager); UT_DEBUGMSG(("Class %x created for charts!\n", GOChartManagerUID)); /* Initialize libgoffice */ libgoffice_init (); cc = GO_CMD_CONTEXT (g_object_new (ABI_CMD_CONTEXT_TYPE, NULL)); go_component_set_command_context (cc); /* Initialize plugins manager */ go_plugins_init (cc, NULL, NULL, NULL, TRUE, GO_TYPE_PLUGIN_LOADER_MODULE); /* Ensure some types are created */ GO_TYPE_DATA_SCALAR_STR; GO_TYPE_DATA_VECTOR_STR; GO_TYPE_DATA_SCALAR_VAL; GO_TYPE_DATA_VECTOR_VAL; GO_TYPE_DATA_MATRIX_VAL; // Add to AbiWord's menus. mime_types = go_components_get_mime_types (); g_slist_foreach (mime_types, (GFunc) create_manager_cb, pApp); AbiGOffice_addToMenus(); return 1; } ABI_FAR_CALL int abi_plugin_unregister (XAP_ModuleInfo * mi) { mi->name = 0; mi->desc = 0; mi->version = 0; mi->author = 0; mi->usage = 0; IE_Imp::unregisterImporter (m_impSniffer); delete m_impSniffer; m_impSniffer = 0; IE_Imp::unregisterImporter (m_impCSniffer); delete m_impCSniffer; m_impCSniffer = 0; pGOChartManager->removeContextualMenu (); XAP_App * pApp = XAP_App::getApp(); pApp->unRegisterEmbeddable(GOChartManagerUID); DELETEP(pGOChartManager); GSList *l = mime_types; while (l) { if (go_components_support_clipboard ((const char*)l->data)) pApp->deleteClipboardFmt((const char*)l->data); l = l->next; } ManagerStruct *s; while (ComponentManagers.getDepth () > 0) { ComponentManagers.pop ((void**)&s); pApp->unRegisterEmbeddable(s->UID); DELETEP(s->Manager); DELETEP(s); } AbiGOffice_removeFromMenus(); go_component_set_command_context (NULL); g_object_unref (cc); return 1; } ABI_FAR_CALL int abi_plugin_supports_version (G_GNUC_UNUSED UT_uint32 major, G_GNUC_UNUSED UT_uint32 minor, G_GNUC_UNUSED UT_uint32 release) { return 1; } cairo_status_t abi_CairoWrite(UT_ByteBuf * buf, unsigned char * data, unsigned int length) { return (buf->append (static_cast(data), static_cast(length)))? CAIRO_STATUS_SUCCESS: CAIRO_STATUS_WRITE_ERROR; }