/* AbiWord * Copyright (C) 1998 AbiSource, Inc. * * 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 "ap_Features.h" #include "ut_assert.h" #include "ut_string.h" #include "ut_debugmsg.h" #include "ut_misc.h" #include "xap_Dialog_Id.h" #include "xap_DialogFactory.h" #include "xap_Dlg_MessageBox.h" #include "fl_SectionLayout.h" #include "fp_Page.h" #include "fl_DocLayout.h" #include "fl_BlockLayout.h" #include "ut_misc.h" #include "ap_TopRuler.h" #include "pd_Style.h" #include "ap_Dialog_Styles.h" #include "ut_string_class.h" #include "ap_Strings.h" #include "ap_Dialog_Id.h" #include "xap_Dlg_Language.h" #include "ap_Dialog_Lists.h" #include "ap_Dialog_Tab.h" AP_Dialog_Styles::AP_Dialog_Styles(XAP_DialogFactory * pDlgFactory, XAP_Dialog_Id id) : XAP_Dialog_NonPersistent(pDlgFactory,id, "interface/dialogstyles") { m_answer = a_OK; m_pParaPreview = NULL; m_pCharPreview = NULL; m_pAbiPreview = NULL; } AP_Dialog_Styles::~AP_Dialog_Styles(void) { UT_sint32 i; DELETEP(m_pParaPreview); DELETEP(m_pCharPreview); DELETEP(m_pAbiPreview); for(i=0; igetBlockFormat(¶Props,false); // // This line expands all styles getView()->getBlockFormat(¶Props,true); const gchar ** charProps = NULL; // getView()->getCharFormat(&charProps,false); // // This line expans all styles.. // getView()->getCharFormat(&charProps,true); UT_sint32 i =0; // // Loop over all properties and add them to our vector // m_vecAllProps.clear(); const gchar * szName = NULL; const gchar * szValue = NULL; while(paraProps[i] != NULL) { szName = paraProps[i]; szValue = paraProps[i+1]; if(strstr(szName,"toc-") == NULL) { addOrReplaceVecProp(szName,szValue); } i = i + 2; } i = 0; while(charProps[i] != NULL) { szName = charProps[i]; szValue = charProps[i+1]; addOrReplaceVecProp(szName,szValue); i = i + 2; } } /*! * This method takes a style and extracts all the properties associated with it and * place them in a properties and attributes vector for easy modification by * the code. */ void AP_Dialog_Styles::fillVecWithProps(const gchar * szStyle, bool bReplaceAttributes = true) { PD_Style * pStyle = NULL; m_vecAllProps.clear(); if( bReplaceAttributes) m_vecAllAttribs.clear(); if(szStyle == NULL || ! getDoc()->getStyle(szStyle,&pStyle)) { return; } const static gchar * paraFields[] = {"text-align", "text-indent", "margin-left", "margin-right", "margin-top", "margin-bottom", "line-height","tabstops","start-value","list-delim", "list-style","list-decimal","field-font","field-color", "keep-together","keep-with-next","orphans","widows","dom-dir"}; const size_t nParaFlds = sizeof(paraFields)/sizeof(paraFields[0]); const static gchar * charFields[] = {"bgcolor","color","font-family","font-size","font-stretch","font-style", "font-variant", "font-weight","text-decoration","lang"}; const size_t nCharFlds = sizeof(charFields)/sizeof(charFields[0]); const static gchar * attribs[] = {PT_FOLLOWEDBY_ATTRIBUTE_NAME,PT_BASEDON_ATTRIBUTE_NAME,PT_LISTID_ATTRIBUTE_NAME,PT_PARENTID_ATTRIBUTE_NAME,PT_LEVEL_ATTRIBUTE_NAME,PT_NAME_ATTRIBUTE_NAME,PT_STYLE_ATTRIBUTE_NAME,PT_TYPE_ATTRIBUTE_NAME}; const size_t nattribs = sizeof(attribs)/sizeof(attribs[0]); UT_uint32 i; UT_DEBUGMSG(("Looking at Style %s \n",szStyle)); UT_Vector vecAllProps; vecAllProps.clear(); // // Loop through all Paragraph properties and add those with non-null values // for(i = 0; i < nParaFlds; i++) { const gchar * szName = paraFields[i]; const gchar * szValue = NULL; pStyle->getProperty(szName,szValue); if(szValue) addOrReplaceVecProp(szName, szValue); } // // Loop through all Character properties and add those with non-null values // for(i = 0; i < nCharFlds; i++) { const gchar * szName = charFields[i]; const gchar * szValue = NULL; pStyle->getProperty(szName,szValue); if(szValue) { xxx_UT_DEBUGMSG(("Adding char prop %s value %s \n",szName,szValue)); addOrReplaceVecProp(szName, szValue); } } // // Loop through all the attributes and add those with non-null values // xxx_UT_DEBUGMSG(("Replace Attributes %d \n",bReplaceAttributes)); if(bReplaceAttributes) { UT_Vector vecAllAtts; vecAllAtts.clear(); for(i = 0; i < nattribs; i++) { const gchar * szName = attribs[i]; const gchar * szValue = NULL; pStyle->getAttributeExpand(szName,szValue); if(szValue) addOrReplaceVecAttribs(szName, szValue); } } else { UT_DEBUGMSG(("Attributes NOT updated \n")); } } /*! * This method returns a std::string of the const char * value associated with the * the property szProp. Stolen from ap_Dialog_Lists and ap_Dialog_Styles. * It assumes properties and values are stored the array like this: * vecProp(n) : vecProp(n+1) * "property" : "value" */ const std::string AP_Dialog_Styles::getPropsVal(const gchar * szProp) const { UT_sint32 i = m_vecAllProps.getItemCount(); if(i <= 0) return ""; UT_sint32 j; const gchar * pszV = NULL; for(j= 0; jgetItemCount(); if(i <= 0) return NULL; UT_sint32 j; const gchar * pszV = NULL; for(j= 0; jgetNthItem(j); if( (pszV != NULL) && (strcmp( pszV,szProp) == 0)) break; } if( j < i ) return (const gchar *) v->getNthItem(j+1); else return NULL; } /*! * This method runs the language dialog to allow the user to set the language * property of their style. */ void AP_Dialog_Styles::ModifyLang(void) { UT_DEBUGMSG(("DOM: modify lang\n")); XAP_Dialog_Id id = XAP_DIALOG_ID_LANGUAGE; XAP_DialogFactory * pDialogFactory = (XAP_DialogFactory *) getFrame()->getDialogFactory(); XAP_Dialog_Language * pDialog = (XAP_Dialog_Language *)(pDialogFactory->requestDialog(id)); UT_return_if_fail (pDialog); const gchar ** props_in = NULL; if (getView()->getCharFormat(&props_in)) { pDialog->setLanguageProperty(UT_getAttribute("lang", props_in)); FREEP(props_in); } pDialog->runModal(getFrame()); bool bOK = (pDialog->getAnswer() == XAP_Dialog_Language::a_OK); if (bOK) { static gchar lang[50]; const gchar * s; pDialog->getChangedLangProperty(&s); sprintf(lang,"%s",s); addOrReplaceVecProp("lang", lang); } pDialogFactory->releaseDialog(pDialog); } /*! * This method runs the tabs dialog to allow the user to edit the character * properties of their style. */ void AP_Dialog_Styles::ModifyFont(void) { // // Fire up the Font Chooser dialog. Code stolen straight from ap_EditMethods. // XAP_Dialog_Id id = XAP_DIALOG_ID_FONT; XAP_DialogFactory * pDialogFactory = (XAP_DialogFactory *) getFrame()->getDialogFactory(); XAP_Dialog_FontChooser * pDialog = (XAP_Dialog_FontChooser *)(pDialogFactory->requestDialog(id)); UT_return_if_fail (pDialog); // stuff the GR_Graphics into the dialog so that it // can query the system for font info relative to our // context. pDialog->setGraphicsContext(getView()->getLayout()->getGraphics()); // stuff font properties into the dialog. // for a/p which are constant across the selection (always // present) we will set the field in the dialog. for things // which change across the selection, we ask the dialog not // to set the field (by passing ""). const std::string sFontFamily = getPropsVal("font-family"); const std::string sFontSize = getPropsVal("font-size"); const std::string sFontWeight = getPropsVal("font-weight"); const std::string sFontStyle = getPropsVal("font-style"); const std::string sColor = getPropsVal("color"); const std::string sBGColor = getPropsVal("bgcolor"); pDialog->setFontFamily(sFontFamily); pDialog->setFontSize(sFontSize); pDialog->setFontWeight(sFontWeight); pDialog->setFontStyle(sFontStyle); pDialog->setColor(sColor); pDialog->setBGColor(sBGColor); // // Set the background color for the preview // static gchar background[8]; const UT_RGBColor * bgCol = getView()->getCurrentPage()->getFillType()->getColor(); sprintf(background, "%02x%02x%02x",bgCol->m_red, bgCol->m_grn,bgCol->m_blu); pDialog->setBackGroundColor( (const gchar *) background); // these behave a little differently since they are // probably just check boxes and we don't have to // worry about initializing a combo box with a choice // (and because they are all stuck under one CSS attribute). bool bUnderline2 = false; bool bOverline2 = false; bool bStrikeOut2 = false; bool bTopline2 = false; bool bBottomline2 = false; const std::string sDecoration = getPropsVal("text-decoration"); if (!sDecoration.empty()) { bUnderline2 = (strstr(sDecoration.c_str(), "underline") != NULL); bOverline2 = (strstr(sDecoration.c_str(), "overline") != NULL); bStrikeOut2 = (strstr(sDecoration.c_str(), "line-through") != NULL); bTopline2 = (strstr(sDecoration.c_str(), "topline") != NULL); bBottomline2 = (strstr(sDecoration.c_str(), "bottomline") != NULL); } pDialog->setFontDecoration(bUnderline2,bOverline2,bStrikeOut2,bTopline2,bBottomline2); /* bool bDirection; s = UT_getAttribute("dir", props_in); if (s) { bDirection = (strstr(s, "rtl") != NULL); } pDialog->setDirection(bDirection); */ // run the dialog pDialog->runModal(getFrame()); // extract what they did bool bOK = (pDialog->getAnswer() == XAP_Dialog_FontChooser::a_OK); if (bOK) { const gchar * s1; if (pDialog->getChangedFontFamily(&s1)) { addOrReplaceVecProp("font-family", s1); } if (pDialog->getChangedFontSize(&s1)) { addOrReplaceVecProp("font-size", s1); } if (pDialog->getChangedFontWeight(&s1)) { addOrReplaceVecProp("font-weight", s1); } if (pDialog->getChangedFontStyle(&s1)) { addOrReplaceVecProp("font-style", s1); } if (pDialog->getChangedColor(&s1)) { addOrReplaceVecProp("color", s1); } if (pDialog->getChangedBGColor(&s1)) { addOrReplaceVecProp("bgcolor", s1); } bool bUnderline = false; bool bChangedUnderline = pDialog->getChangedUnderline(&bUnderline); bool bOverline = false; bool bChangedOverline = pDialog->getChangedOverline(&bOverline); bool bStrikeOut = false; bool bChangedStrikeOut = pDialog->getChangedStrikeOut(&bStrikeOut); bool bTopline = false; bool bChangedTopline = pDialog->getChangedTopline(&bTopline); bool bBottomline = false; bool bChangedBottomline = pDialog->getChangedBottomline(&bBottomline); /* bool bDirection = false; bool bChangedDirection = pDialog->getChangedDirection(&bDirection); */ if (bChangedUnderline || bChangedStrikeOut || bChangedOverline || bChangedTopline || bChangedBottomline) { UT_String decors; static gchar s[50]; decors.clear(); if(bUnderline) decors += "underline "; if(bStrikeOut) decors += "line-through "; if(bOverline) decors += "overline "; if(bTopline) decors += "topline "; if(bBottomline) decors += "bottomline "; if(!bUnderline && !bStrikeOut && !bOverline && !bTopline && !bBottomline) decors = "none"; sprintf(s,"%s",decors.c_str()); addOrReplaceVecProp("text-decoration", s); } /* if(bChangedDirection) { if (bDirection == 1) s = "rtl"; else s = "ltr"; addOrReplaceVecProp("dir", s); } */ } pDialogFactory->releaseDialog(pDialog); } /*! * Used for the Tabs dialog to extract info from the tabs dialog. */ void AP_Dialog_Styles::_tabCallback(const char *szTabStops, const char *szDflTabStop) { // TODO: fix mem leaks if (szTabStops) addOrReplaceVecProp("tabstops", g_strdup(szTabStops)); if (szDflTabStop) addOrReplaceVecProp("default-tab-interval", g_strdup(szDflTabStop)); } /*! * Used to extract data out of the Tabs dialog. */ static void s_TabSaveCallBack (AP_Dialog_Tab * /*pDlg*/, FV_View * /*pView*/, const char * szTabStops, const char * szDflTabStop, void * closure) { UT_return_if_fail (closure); AP_Dialog_Styles * pStyleDlg = static_cast(closure); pStyleDlg->_tabCallback(szTabStops, szDflTabStop); } /*! * This method fires up the Tabs dialog to allow the user to edit the properties * associated with Tabs for their style. */ void AP_Dialog_Styles::ModifyTabs(void) { // // Fire up the Tab dialog // XAP_Dialog_Id id = AP_DIALOG_ID_TAB; XAP_DialogFactory * pDialogFactory = (XAP_DialogFactory *) getFrame()->getDialogFactory(); AP_Dialog_Tab * pDialog = (AP_Dialog_Tab *)(pDialogFactory->requestDialog(id)); UT_return_if_fail (pDialog); pDialog->setSaveCallback(s_TabSaveCallBack, (void *)this); pDialog->runModal(getFrame()); pDialogFactory->releaseDialog(pDialog); } /*! * This method runs the Lists dialog in amodal way so the user easily edit numbering * properties. */ void AP_Dialog_Styles::ModifyLists(void) { UT_DEBUGMSG(("DOM: Doing stuff in Modify Lists \n")); UT_GenericVector vp; // // Fire up a Modal version of Lists dialog // XAP_DialogFactory * pDialogFactory = (XAP_DialogFactory *) getFrame()->getDialogFactory(); // // Use this method so that we can have modeless Lists dialog and this // modal version simultaneously // AP_Dialog_Lists * pDialog = (AP_Dialog_Lists *)(pDialogFactory->justMakeTheDialog(AP_DIALOG_ID_LISTS)); UT_return_if_fail (pDialog); // // Fill input list for Lists dialog // const std::string sListStyle = getPropsVal("list-style"); const std::string sFieldFont = getPropsVal("field-font"); const std::string sStartValue = getPropsVal("start-value"); const std::string sListDelim = getPropsVal("list-delim"); const std::string sMarginLeft = getPropsVal("margin-left"); const std::string sListDecimal = getPropsVal("list-decimal"); const std::string sTextIndent = getPropsVal("text-indent"); if(!sListStyle.empty()) { vp.addItem("list-style"); vp.addItem(sListStyle.c_str()); } if(!sFieldFont.empty()) { vp.addItem("field-font"); vp.addItem(sFieldFont.c_str()); } if(!sStartValue.empty()) { vp.addItem("start-value"); vp.addItem(sStartValue.c_str()); } if(!sListDelim.empty()) { vp.addItem("list-delim"); vp.addItem(sListDelim.c_str()); } if(!sMarginLeft.empty()) { vp.addItem("margin-left"); vp.addItem(sMarginLeft.c_str()); } // TODO: Why is field-font here twice? if(!sFieldFont.empty()) { vp.addItem("field-font"); vp.addItem(sFieldFont.c_str()); } if(!sListDecimal.empty()) { vp.addItem("list-decimal"); vp.addItem(sListDecimal.c_str()); } if(!sTextIndent.empty()) { vp.addItem("text-indent"); vp.addItem(sTextIndent.c_str()); } pDialog->fillDialogFromVector(&vp); // // Actually run the dialog // pDialog->runModal(getFrame()); if(pDialog->getAnswer() == AP_Dialog_Lists::a_OK) { // // Extract the properties // UT_DEBUGMSG(("SEVIOR: Lists data should be changed. \n")); const UT_Vector * vo = pDialog->getOutProps(); if(getVecVal(vo,"list-style")) { m_ListProps[0] = getVecVal(vo,"list-style"); UT_DEBUGMSG(("SEVIOR: list-style %s \n",m_ListProps[0].c_str())); addOrReplaceVecProp("list-style",m_ListProps[0].c_str()); } if(getVecVal(vo,"start-value")) { m_ListProps[1] = getVecVal(vo,"start-value"); UT_DEBUGMSG(("SEVIOR: start-value %s \n",m_ListProps[1].c_str())); addOrReplaceVecProp("start-value",m_ListProps[1].c_str()); } if(getVecVal(vo,"list-delim")) { m_ListProps[2] = getVecVal(vo,"list-delim"); UT_DEBUGMSG(("SEVIOR: list-delim %s \n",m_ListProps[2].c_str())); addOrReplaceVecProp("list-delim",m_ListProps[2].c_str()); } if(getVecVal(vo,"margin-left")) { m_ListProps[3] = getVecVal(vo,"margin-left"); addOrReplaceVecProp("margin-left",m_ListProps[3].c_str()); } if(getVecVal(vo,"field-font")) { m_ListProps[4] = getVecVal(vo,"field-font"); addOrReplaceVecProp("field-font",m_ListProps[4].c_str()); } if(getVecVal(vo,"list-decimal")) { m_ListProps[5] = getVecVal(vo,"list-decimal"); addOrReplaceVecProp("list-decimal",m_ListProps[5].c_str()); } if(getVecVal(vo,"text-indent")) { m_ListProps[6] = getVecVal(vo,"text-indent"); addOrReplaceVecProp("text-indent",m_ListProps[6].c_str()); } // TODO: Why is field-font here twice? if(getVecVal(vo,"field-font")) { m_ListProps[7] = getVecVal(vo,"field-font"); addOrReplaceVecProp("field-font",m_ListProps[7].c_str()); } // // Whew we're done! // } delete pDialog; } /*! * Fire up the Paragraph dialog so we can modify the paragraph properties */ void AP_Dialog_Styles::ModifyParagraph(void) { XAP_DialogFactory * pDialogFactory = (XAP_DialogFactory *)(getFrame()->getDialogFactory()); AP_Dialog_Paragraph * pDialog = (AP_Dialog_Paragraph *)(pDialogFactory->requestDialog(AP_DIALOG_ID_PARAGRAPH)); UT_return_if_fail (pDialog); const static gchar * paraFields[] = {"text-align", "text-indent", "margin-left", "margin-right", "margin-top", "margin-bottom", "line-height","tabstops","start-value","list-delim", "list-decimal","list-style","field-font","field-color", "keep-together","keep-with-next","orphans","widows","dom-dir"}; const size_t NUM_PARAPROPS = sizeof(paraFields)/sizeof(paraFields[0]); // // Count the number paragraph properties // //#define NUM_PARAPROPS 14 static gchar paraVals[NUM_PARAPROPS][60]; const gchar ** props = NULL; UT_uint32 i = 0; if(m_vecAllProps.getItemCount() <= 0) return; UT_uint32 countp = m_vecAllProps.getItemCount() + 1; props = (const gchar **) UT_calloc(countp, sizeof(gchar *)); countp--; for(i=0; isetDialogData(props)) return; FREEP(props); // let's steal the width from getTopRulerInfo. AP_TopRulerInfo info; getView()->getTopRulerInfo(&info); pDialog->setMaxWidth (info.u.c.m_xColumnWidth); // run the dialog pDialog->runModal(getFrame()); // get the dialog answer AP_Dialog_Paragraph::tAnswer answer = pDialog->getAnswer(); const gchar ** propitem = NULL; if(answer == AP_Dialog_Paragraph::a_OK) { // getDialogData() returns us gchar ** data we have to g_free pDialog->getDialogData(props); UT_return_if_fail (props); // set properties into the vector. We have to save these as static char // strings so they persist past this method. if (props && props[0]) { const gchar * szVals = NULL; for(i=0; ireleaseDialog(pDialog); } /*! * Extract all the props from the vector and apply them to the abi preview. We use * the style "tmp" to display the current style in the preview. */ void AP_Dialog_Styles::updateCurrentStyle(void) { if(m_pAbiPreview == NULL) return; const gchar ** props = NULL; UT_sint32 i = 0; if(m_vecAllProps.getItemCount() <= 0) return; UT_sint32 countp = m_vecAllProps.getItemCount() + 1; props = (const gchar **) UT_calloc(countp, sizeof(gchar *)); countp--; for(i=0; igetStyle("tmp", &pStyle); // // clear out old description // m_curStyleDesc.clear(); for(i=0; igetStyle(szBasedon,&pBasedon)) { UT_Vector vecProps; pBasedon->getAllProperties(&vecProps,0); for(i=0; iappendStyle(attrib); } else { const gchar * atts[3] = {"props",NULL,NULL}; atts[1] = fullProps.c_str(); getLDoc()->addStyleAttributes("tmp",atts); getLDoc()->updateDocForStyleChange("tmp",true); } getLView()->setPoint(m_posFocus+1); getLView()->setStyle("tmp"); drawLocal(); FREEP(props); } /*! * Take the current style description and use it to define a new style * in the main document. */ bool AP_Dialog_Styles::createNewStyle(const gchar * szName) { UT_DEBUGMSG(("DOM: new style %s\n", szName)); const gchar ** props = NULL; UT_uint32 i = 0; if(m_vecAllProps.getItemCount() <= 0) return false; UT_uint32 countp = m_vecAllProps.getItemCount() + 1; props = (const gchar **) UT_calloc(countp, sizeof(gchar *)); countp--; for(i=0; igetStyle("szName", &pStyle); if(pStyle != NULL) return false; // // Assemble the attributes we need for this new style // const gchar * attrib[] = {PT_NAME_ATTRIBUTE_NAME,szName,PT_TYPE_ATTRIBUTE_NAME,getAttsVal(PT_TYPE_ATTRIBUTE_NAME),"basedon",getAttsVal("basedon"),"followedby",getAttsVal("followedby"),"props",m_curStyleDesc.c_str(),NULL,NULL}; bool bres = getDoc()->appendStyle(attrib); FREEP(props); return bres; } /*! * Take the current style description and modify the description of the style * in the main document. */ bool AP_Dialog_Styles::applyModifiedStyleToDoc(void) { const gchar ** props = NULL; UT_uint32 i = 0; if(m_vecAllProps.getItemCount() <= 0) return false; UT_uint32 countp = m_vecAllProps.getItemCount() + 1; props = (const gchar **) UT_calloc(countp, sizeof(gchar *)); countp--; for(i=0; isetAllStyleAttributes(szStyle,attribs); FREEP(props); FREEP(attribs); return bres; } /*! * Pointer to the current FV_View of the document we're working with. */ void AP_Dialog_Styles::setView( FV_View * pView) { m_pView = pView; } /*! * Pointer to the frame of the real document we're working with. */ void AP_Dialog_Styles::setFrame( XAP_Frame * pFrame) { m_pFrame = pFrame; } /*! * Pointer to current the PD_Document for real document we're working with. */ void AP_Dialog_Styles::setDoc( PD_Document * pDoc) { m_pDoc = pDoc; } /*! * Pointer to the current FV_View of the document we're working with. */ FV_View * AP_Dialog_Styles::getView(void) const { return m_pView; } /*! * Pointer to the frame of the real document we're working with. */ XAP_Frame * AP_Dialog_Styles::getFrame(void) const { return m_pFrame; } /*! * Pointer to current the PD_Document for real document we're working with. */ PD_Document * AP_Dialog_Styles::getDoc(void) const { return m_pDoc; } /*! * Create the preview for the Paragraph preview for styles. */ void AP_Dialog_Styles::_createParaPreviewFromGC(GR_Graphics * gc, UT_uint32 width, UT_uint32 height) { UT_return_if_fail (gc); const XAP_StringSet * pSS = m_pApp->getStringSet(); UT_return_if_fail (pSS); UT_UCSChar * str; UT_UCS4_cloneString_char (&str, pSS->getValue(AP_STRING_ID_DLG_Styles_LBL_TxtMsg)); m_pParaPreview = new AP_Preview_Paragraph(gc, str, static_cast(this)); UT_return_if_fail (m_pParaPreview); FREEP(str); m_pParaPreview->setWindowSize(width, height); } void AP_Dialog_Styles::_createCharPreviewFromGC(GR_Graphics * gc, UT_uint32 width, UT_uint32 height) { UT_return_if_fail (gc); const XAP_StringSet * pSS = m_pApp->getStringSet(); UT_return_if_fail (pSS); // // Set the Background color for the preview. // static gchar background[8]; const UT_RGBColor * bgCol = getView()->getCurrentPage()->getFillType()->getColor(); sprintf(background, "%02x%02x%02x",bgCol->m_red,bgCol->m_grn,bgCol->m_blu); m_pCharPreview = new XAP_Preview_FontPreview(gc,background); UT_return_if_fail (m_pCharPreview); m_pCharPreview->setWindowSize(width, height); // // Text for the Preview // static UT_UCSChar szString[60]; UT_UCS4_strcpy_char( (UT_UCSChar *) szString, pSS->getValue(AP_STRING_ID_DLG_Styles_LBL_TxtMsg)); m_pCharPreview->setDrawString((const UT_UCSChar *) szString); // // set our Vector of Character Properties into the preview class. // m_pCharPreview->setVecProperties( &m_mapCharProps); } /*! * This is the preview for the second dialog pane. It puts a complete mini-abiword * in a graphics context so all the results of any style change is immediately * obvious. */ void AP_Dialog_Styles::_createAbiPreviewFromGC(GR_Graphics * gc, UT_uint32 width, UT_uint32 height ) { UT_return_if_fail (gc); if(m_pAbiPreview) DELETEP(m_pAbiPreview); m_pAbiPreview = new AP_Preview_Abi(gc,width,height,getFrame(),PREVIEW_ZOOMED); UT_return_if_fail (m_pAbiPreview); } /*! * This is the FV_View pointer for our mini-abi in the second pane preview. */ FV_View * AP_Dialog_Styles::getLView(void) const { return m_pAbiPreview->getView(); } /*! * This is the pd_Document pointer for our mini-Abi in the second pane preview. */ PD_Document * AP_Dialog_Styles::getLDoc(void) const { return m_pAbiPreview->getDoc(); } /*! * This updates the mini-Abi in the second pane preview. */ void AP_Dialog_Styles::drawLocal(void) { if(m_pAbiPreview) { m_pAbiPreview->draw(); } } /*! * This puts some tet in the second pane preview so we can see the effect of the * Styles. */ void AP_Dialog_Styles::_populateAbiPreview(bool isNew) { // // Text for the Preview // static UT_UCSChar szString[60]; static UT_UCSChar sz1[4]; static UT_UCSChar sz2[4]; static UT_UCSChar sz3[4]; static UT_UCSChar szSpace[4]; const XAP_StringSet * pSS = m_pApp->getStringSet(); UT_UCS4_strcpy_char( (UT_UCSChar *) szString, pSS->getValue(AP_STRING_ID_DLG_Styles_LBL_TxtMsg)); UT_UCS4_strcpy_char( (UT_UCSChar *) sz1, " 1"); UT_UCS4_strcpy_char( (UT_UCSChar *) sz2, " 2"); UT_UCS4_strcpy_char( (UT_UCSChar *) sz3, " 3"); UT_UCS4_strcpy_char( (UT_UCSChar *) szSpace, " "); UT_uint32 len =UT_UCS4_strlen(szString); UT_uint32 len1 =UT_UCS4_strlen(sz1); UT_uint32 lenSpace =UT_UCS4_strlen(szSpace); const char * szStyle = NULL; if(!isNew) { szStyle = getCurrentStyle(); } // // Set all the margins to 0 // const gchar * props[] = {"page-margin-left","0.0in", "page-margin-right","0.0in", "page-margin-top","0.0in", "page-margin-bottom","0.0in", "page-margin-footer","0.0in", "page-margin-header","0.0in",NULL}; getLView()->setSectionFormat(props); // // First Paragraph // m_posBefore = getLView()->getPoint(); UT_uint32 i=0; for(i=0;i<15;i++) { getLView()->cmdCharInsert((UT_UCSChar *) szString,len); getLView()->cmdCharInsert((UT_UCSChar *) szSpace,lenSpace); } getLView()->cmdCharInsert((UT_UCSChar *) sz1,len1); const gchar * pszFGColor = NULL; const gchar * pszBGColor = NULL; static gchar Grey[8]; static gchar szFGColor[8]; UT_RGBColor FGColor(0,0,0); UT_RGBColor BGColor(255,255,255); const UT_RGBColor * pageCol = NULL; getLView()->setStyle("Normal"); const gchar ** props_in = NULL; getLView()->getCharFormat(&props_in); pszFGColor = UT_getAttribute("color", props_in); pszBGColor = UT_getAttribute("bgcolor",props_in); if(pszFGColor != NULL) UT_parseColor(pszFGColor,FGColor); // // Save the Foreground color for later // sprintf(szFGColor, "%02x%02x%02x",FGColor.m_red, FGColor.m_grn, FGColor.m_blu); if(pszBGColor == NULL) { pageCol = getLView()->getCurrentPage()->getFillType()->getColor(); sprintf(Grey, "%02x%02x%02x",(pageCol->m_red+FGColor.m_red)/2, (pageCol->m_grn+FGColor.m_grn)/2, (pageCol->m_blu+FGColor.m_blu)/2); } else if(strcmp(pszBGColor,"transparent")==0) { pageCol = getLView()->getCurrentPage()->getFillType()->getColor(); sprintf(Grey, "%02x%02x%02x",(pageCol->m_red+FGColor.m_red)/2, (pageCol->m_grn+FGColor.m_grn)/2, (pageCol->m_blu+FGColor.m_blu)/2); } else { UT_parseColor(pszBGColor,BGColor); sprintf(Grey, "%02x%02x%02x",(BGColor.m_red+FGColor.m_red)/2, (BGColor.m_grn + FGColor.m_grn)/2, (BGColor.m_blu+FGColor.m_blu)/2); } // // Set the "Greyed" color for text in previous block // const gchar * GreyCol[3] = {"color",(const gchar *) Grey,NULL}; getLDoc()->changeSpanFmt(PTC_AddFmt,m_posBefore,getLView()->getPoint(),NULL,GreyCol); getLView()->insertParagraphBreak(); // // Second Paragraph in focus. Our Vectors containing the current settings have // been filled from calls in the platform layer. // // Attributes // UT_uint32 counta = m_vecAllAttribs.getItemCount()+1; const gchar ** latt = NULL; latt = (const gchar **) UT_calloc(counta, sizeof(gchar *)); counta--; for(i=0; igetStyle("tmp", &pStyle); // // clear out old description // m_curStyleDesc.clear(); for(i=0; iappendStyle(attrib); } else { getLDoc()->addStyleProperties("tmp",lprop); getLDoc()->addStyleAttributes("tmp",latt); } getLView()->setStyle("tmp"); m_posFocus = getLView()->getPoint(); // // Set Color Back // pszFGColor = UT_getAttribute("color", lprop); if(pszFGColor == NULL) { const gchar * FGCol[3] = {"color",(const gchar *) szFGColor,NULL}; getLView()->setCharFormat(FGCol); } FREEP(lprop); for(i=0; i<8; i++) { getLView()->cmdCharInsert((UT_UCSChar *) szString,len); getLView()->cmdCharInsert((UT_UCSChar *) szSpace,lenSpace); } getLView()->cmdCharInsert((UT_UCSChar *) sz2,len1); // // Third Paragraph // getLView()->insertParagraphBreak(); m_posAfter = getLView()->getPoint(); getLView()->setCharFormat(GreyCol); for(i=0; i<15; i++) { getLView()->cmdCharInsert((UT_UCSChar *) szString,len); getLView()->cmdCharInsert((UT_UCSChar *) szSpace,lenSpace); } getLView()->cmdCharInsert((UT_UCSChar *) sz3,len1); } /*! * remove the mini-Abi preview in the second pane. */ void AP_Dialog_Styles::destroyAbiPreview(void) { DELETEP(m_pAbiPreview); } ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// void AP_Dialog_Styles::event_paraPreviewUpdated (const gchar * pageLeftMargin, const gchar * pageRightMargin, const gchar * align, const gchar * firstLineIndent, const gchar * leftIndent, const gchar * rightIndent, const gchar * beforeSpacing, const gchar * afterSpacing, const gchar * lineSpacing) const { // Whomever designed this preview and the Paragraph dialog should be shot AP_Dialog_Paragraph::tAlignState tAlign = AP_Dialog_Paragraph::align_LEFT; AP_Dialog_Paragraph::tIndentState tIndent = AP_Dialog_Paragraph::indent_NONE; AP_Dialog_Paragraph::tSpacingState tSpacing = AP_Dialog_Paragraph::spacing_MULTIPLE; const char * sz = NULL; const char * pPlusFound = NULL; UT_return_if_fail (m_pParaPreview); if (!align) goto LblIndent; // skip to the next label if nothing's set here if (!strcmp(align, "right")) tAlign = AP_Dialog_Paragraph::align_RIGHT; else if (!strcmp(align, "center")) tAlign = AP_Dialog_Paragraph::align_CENTERED; else if (!strcmp(align, "justify")) tAlign = AP_Dialog_Paragraph::align_JUSTIFIED; LblIndent: if (!firstLineIndent) goto LblSpacing; sz = (const char *)firstLineIndent; if (UT_convertDimensionless(sz) > (double) 0) { tIndent = AP_Dialog_Paragraph::indent_FIRSTLINE; } else if (UT_convertDimensionless(sz) < (double) 0) { tIndent = AP_Dialog_Paragraph::indent_HANGING; } LblSpacing: if (!lineSpacing) goto LblSet; sz = (const char *)lineSpacing; pPlusFound = strrchr(sz, '+'); if (pPlusFound && *(pPlusFound + 1) == 0) tSpacing = AP_Dialog_Paragraph::spacing_ATLEAST; { if(UT_hasDimensionComponent(sz)) tSpacing = AP_Dialog_Paragraph::spacing_EXACTLY; else if(!strcmp("1.0", sz)) tSpacing = AP_Dialog_Paragraph::spacing_SINGLE; else if(!strcmp("1.5", sz)) tSpacing = AP_Dialog_Paragraph::spacing_ONEANDHALF; else if(!strcmp("2.0", sz)) tSpacing = AP_Dialog_Paragraph::spacing_DOUBLE; } LblSet: m_pParaPreview->setFormat (pageLeftMargin, pageRightMargin, tAlign, firstLineIndent, tIndent, leftIndent, rightIndent, beforeSpacing, afterSpacing, lineSpacing, tSpacing); // force a redraw m_pParaPreview->draw(); } /*! * Update the character preview in the front pane. */ void AP_Dialog_Styles::event_charPreviewUpdated (void) const { UT_return_if_fail (m_pCharPreview); // add this when we make a char preview // force a redraw m_pCharPreview->setVecProperties( &m_mapCharProps); m_pCharPreview->draw(); } /*! * Fill both the paragraph and character previews in the front pane with some * Text so we can see the text of the chosen style. */ void AP_Dialog_Styles::_populatePreviews(bool isModify) { PD_Style * pStyle = NULL; const char * szStyle = NULL; const static gchar * paraFields[] = {"text-align", "text-indent", "margin-left", "margin-right", "margin-top", "margin-bottom", "line-height","tabstops","start-value","list-delim", "list-style","field-font","list-decimal","field-color", "keep-together","keep-with-next","orphans","widows","dom-dir"}; const size_t nParaFlds = sizeof(paraFields)/sizeof(paraFields[0]); const gchar * paraValues [nParaFlds]; const static gchar * charFields[] = {"bgcolor","color","font-family","font-size","font-stretch","font-style", "font-variant", "font-weight","text-decoration","lang"}; const size_t nCharFlds = sizeof(charFields)/sizeof(charFields[0]); const gchar * charValues [nCharFlds]; szStyle = getCurrentStyle(); if (!szStyle) // having nothing displayed is totally valid { return; } // // Load up our properties vector // fillVecWithProps(szStyle,true); // update the previews and the description label if (getDoc()->getStyle (szStyle, &pStyle)) { UT_uint32 i; // // Clear any previous stuff from our style description. This description must // persist beyond this method because we want to modify it. // m_curStyleDesc.clear(); // first loop through and pass out each property:value combination for paragraphs for(i = 0; i < nParaFlds; i++) { const gchar * szName = paraFields[i]; const gchar * szValue = NULL; pStyle->getProperty(szName,szValue); if (szValue == NULL) { pStyle->getPropertyExpand(szName,szValue); if (szValue == NULL) { paraValues[i] = 0; continue; } else { paraValues[i] = szValue; } } else { paraValues[i] = szValue; m_curStyleDesc += (const char *)szName; m_curStyleDesc += ":"; if (szValue && *szValue) m_curStyleDesc += (const char *)szValue; m_curStyleDesc += "; "; } } // Clear out old contents of the char vector if they exist m_mapCharProps.clear(); // now loop through and pass out each property:value combination for characters for(i = 0; i < nCharFlds; i++) { const gchar * szName = charFields[i]; const gchar * szValue = NULL; pStyle->getProperty(szName,szValue); if (szValue == NULL) { pStyle->getPropertyExpand(szName,szValue); if (szValue == NULL) { charValues[i] = 0; continue; } else { charValues[i] = szValue; } } else { m_curStyleDesc += (const char *)szName; m_curStyleDesc += ":"; if(szValue && *szValue) m_curStyleDesc += (const char *)szValue; m_curStyleDesc += "; "; } // // Put them in our property vector for the Character preview // m_mapCharProps[szName] = szValue; } if (!m_curStyleDesc.empty()) { if(!isModify) { setDescription (m_curStyleDesc.c_str()); } else { setModifyDescription (m_curStyleDesc.c_str()); } // these aren't set at a style level, but we need to put them in there anyway const gchar ** props_in = NULL; getView()->getSectionFormat(&props_in); if(!isModify) event_paraPreviewUpdated(UT_getAttribute("page-margin-left", props_in), UT_getAttribute("page-margin-right", props_in), (const gchar *)paraValues[0], (const gchar *)paraValues[1], (const gchar *)paraValues[2], (const gchar *)paraValues[3], (const gchar *)paraValues[4], (const gchar *)paraValues[5], (const gchar *)paraValues[6]); if(!isModify) event_charPreviewUpdated(); } } }