void AP_UnixDialog_Paragraph::event_SpinFocusOut(GtkWidget * widget) { tControl id = (tControl) GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), WIDGET_ID_TAG)); if (m_bEditChanged) { // this function will massage the contents for proper // formatting for spinbuttons that need it. for example, // line spacing can't be negative. _setSpinItemValue(id, (const gchar *) gtk_entry_get_text(GTK_ENTRY(widget))); // to ensure the massaged value is reflected back up // to the screen, we repaint from the member variable _syncControls(id); m_bEditChanged = false; } }
void AP_Dialog_Paragraph::_syncControls(tControl changed, bool /*bAll = false */) { if(changed == id_SPIN_LEFT_INDENT) { // need to check the limits // cannot go past left page margin. // TODO : is there a minimum text width? double leftPageMargin = UT_convertToDimension(m_pageLeftMargin, m_dim); double rightIndent = UT_convertToDimension(_getSpinItemValue(id_SPIN_RIGHT_INDENT), m_dim); if(-UT_convertToDimension(_getSpinItemValue(id_SPIN_LEFT_INDENT), m_dim) > leftPageMargin) { _setSpinItemValue(id_SPIN_LEFT_INDENT, (const gchar *)UT_formatDimensionString(m_dim, -leftPageMargin), op_SYNC); } // nor past pagesize - rightIndent on right. if(UT_convertDimensionless(_getSpinItemValue(id_SPIN_LEFT_INDENT)) > UT_convertInchesToDimension(m_iMaxWidth, m_dim) - rightIndent) { _setSpinItemValue(id_SPIN_LEFT_INDENT, (const gchar *)UT_convertInchesToDimensionString(m_dim, m_iMaxWidth - rightIndent), op_SYNC); } } if(changed == id_SPIN_RIGHT_INDENT) { // need to check the limits // cannot go past right page margin. double rightPageMargin = UT_convertToDimension(m_pageRightMargin, m_dim); double leftIndent = UT_convertToDimension(_getSpinItemValue(id_SPIN_LEFT_INDENT), m_dim); if(-UT_convertToDimension(_getSpinItemValue(id_SPIN_RIGHT_INDENT), m_dim) > rightPageMargin) { _setSpinItemValue(id_SPIN_RIGHT_INDENT, (const gchar *)UT_formatDimensionString(m_dim, -rightPageMargin), op_SYNC); } // nor can we force text left past pagesize, minus left margin if(UT_convertDimensionless(_getSpinItemValue(id_SPIN_RIGHT_INDENT)) > UT_convertInchesToDimension(m_iMaxWidth, m_dim) - leftIndent) { _setSpinItemValue(id_SPIN_RIGHT_INDENT, (const gchar *)UT_convertInchesToDimensionString(m_dim, m_iMaxWidth - leftIndent), op_SYNC); } } if (changed == id_MENU_SPECIAL_INDENT || changed == id_SPIN_SPECIAL_INDENT) { double dDefault = 0.0; bool bDefault = true; double sign = -1.0; if (_getMenuItemValue(id_MENU_SPECIAL_INDENT) == indent_FIRSTLINE) sign = +1.0; if (changed == id_MENU_SPECIAL_INDENT) { switch(_getMenuItemValue(id_MENU_SPECIAL_INDENT)) { case indent_NONE: dDefault = 0.0; break; case indent_FIRSTLINE: case indent_HANGING: // only change to default if existing value is zero dDefault = UT_convertDimensionless(_getSpinItemValue(id_SPIN_SPECIAL_INDENT)); if (dDefault == 0) { bDefault = false; } else { dDefault = 0.5; } break; default: UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); break; } if (bDefault) { if (m_dim != DIM_IN) dDefault = UT_convertInchesToDimension(dDefault, m_dim); const gchar* szNew = UT_convertInchesToDimensionString(m_dim, dDefault, ".1"); _setSpinItemValue(id_SPIN_SPECIAL_INDENT, szNew, op_SYNC); } } else /* (changed == id_SPIN_SPECIAL_INDENT) */ { switch(_getMenuItemValue(id_MENU_SPECIAL_INDENT)) { case indent_NONE: _setMenuItemValue(id_MENU_SPECIAL_INDENT, indent_FIRSTLINE, op_SYNC); break; default: break; } } // if spin contains a negative number, we flip the direction of the indent. double val = UT_convertDimensionless(_getSpinItemValue(id_SPIN_SPECIAL_INDENT)); if (val < 0) { sign = -sign; // sometimes this appears to have no effect. why? if (_getMenuItemValue(id_MENU_SPECIAL_INDENT) == indent_FIRSTLINE) _setMenuItemValue(id_MENU_SPECIAL_INDENT, indent_HANGING, op_SYNC); else if (_getMenuItemValue(id_MENU_SPECIAL_INDENT) == indent_HANGING) _setMenuItemValue(id_MENU_SPECIAL_INDENT, indent_FIRSTLINE, op_SYNC); const gchar* szNew = UT_convertInchesToDimensionString(m_dim, -val, ".1"); _setSpinItemValue(id_SPIN_SPECIAL_INDENT, szNew, op_SYNC); } // sanity check. double leftIndent = UT_convertToDimension(_getSpinItemValue(id_SPIN_LEFT_INDENT), m_dim); double effectiveLeftMargin = leftIndent + (UT_convertToDimension (_getSpinItemValue(id_SPIN_SPECIAL_INDENT), m_dim) * sign); double leftPageMargin = UT_convertToDimension(m_pageLeftMargin, m_dim); double rightIndent = UT_convertToDimension(_getSpinItemValue(id_SPIN_RIGHT_INDENT), m_dim); if(-effectiveLeftMargin > leftPageMargin) { _setSpinItemValue(id_SPIN_SPECIAL_INDENT, (const gchar *)UT_formatDimensionString(m_dim, -leftPageMargin), op_SYNC); } if(effectiveLeftMargin > UT_convertInchesToDimension(m_iMaxWidth, m_dim) - rightIndent) { _setSpinItemValue(id_SPIN_SPECIAL_INDENT, (const gchar *)UT_convertInchesToDimensionString(m_dim, m_iMaxWidth - rightIndent), op_SYNC); } } if (changed == id_SPIN_SPECIAL_SPACING) { switch(_getMenuItemValue(id_MENU_SPECIAL_SPACING)) { case spacing_SINGLE: case spacing_ONEANDHALF: case spacing_DOUBLE: _setMenuItemValue(id_MENU_SPECIAL_SPACING, spacing_MULTIPLE, op_SYNC); break; default: break; } } if (changed == id_MENU_SPECIAL_SPACING) { UT_Dimension dimOld = UT_determineDimension(_getSpinItemValue(id_SPIN_SPECIAL_SPACING), DIM_none); switch(_getMenuItemValue(id_MENU_SPECIAL_SPACING)) { case spacing_SINGLE: _setSpinItemValue(id_SPIN_SPECIAL_SPACING, "1.0", op_SYNC); break; case spacing_ONEANDHALF: _setSpinItemValue(id_SPIN_SPECIAL_SPACING, "1.5", op_SYNC); break; case spacing_DOUBLE: _setSpinItemValue(id_SPIN_SPECIAL_SPACING, "2.0", op_SYNC); break; case spacing_ATLEAST: case spacing_EXACTLY: // only change to default if not dimensioned if (dimOld == DIM_none) _setSpinItemValue(id_SPIN_SPECIAL_SPACING, "12pt", op_SYNC); break; case spacing_MULTIPLE: // only change to default if dimensioned if (dimOld != DIM_none) _setSpinItemValue(id_SPIN_SPECIAL_SPACING, "1.0", op_SYNC); break; default: UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); break; } } // the preview needs to suck in the changed data (to cache it // for subsequent draws) UT_BidiCharType iDir; if(_getCheckItemValue(id_CHECK_DOMDIRECTION) == check_TRUE) iDir = UT_BIDI_RTL; else if(_getCheckItemValue(id_CHECK_DOMDIRECTION) == check_FALSE) iDir = UT_BIDI_LTR; else { // nothing given -- default to LTR UT_DEBUGMSG(("AP_Dialog_Paragraph::_syncControls: no value of dom-dir," " defaulting to LTR\n")); iDir = UT_BIDI_LTR; } m_paragraphPreview->setFormat(m_pageLeftMargin, m_pageRightMargin, (AP_Dialog_Paragraph::tAlignState) _getMenuItemValue(id_MENU_ALIGNMENT), _getSpinItemValue(id_SPIN_SPECIAL_INDENT), (AP_Dialog_Paragraph::tIndentState) _getMenuItemValue(id_MENU_SPECIAL_INDENT), _getSpinItemValue(id_SPIN_LEFT_INDENT), _getSpinItemValue(id_SPIN_RIGHT_INDENT), _getSpinItemValue(id_SPIN_BEFORE_SPACING), _getSpinItemValue(id_SPIN_AFTER_SPACING), _getSpinItemValue(id_SPIN_SPECIAL_SPACING), (AP_Dialog_Paragraph::tSpacingState) _getMenuItemValue(id_MENU_SPECIAL_SPACING), iDir); m_paragraphPreview->queueDraw(); }
void AP_Dialog_Paragraph::_doSpin(tControl edit, UT_sint32 amt) { UT_ASSERT_HARMLESS(amt); // zero makes no sense // get current value from member const gchar* szOld = _getSpinItemValue(edit); double d = UT_convertDimensionless(szOld); // figure out which dimension and units to spin in UT_Dimension dimSpin = m_dim; double dSpinUnit = SPIN_INCR_PT; double dMin = 0.0; bool bMin = false; switch (edit) { case id_SPIN_SPECIAL_INDENT: dMin = 0.0; bMin = true; // fall through case id_SPIN_LEFT_INDENT: case id_SPIN_RIGHT_INDENT: dimSpin = m_dim; switch (dimSpin) { case DIM_IN: dSpinUnit = SPIN_INCR_IN; break; case DIM_CM: dSpinUnit = SPIN_INCR_CM; break; case DIM_PI: dSpinUnit = SPIN_INCR_PI; break; case DIM_PT: dSpinUnit = SPIN_INCR_PT; break; default: UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); break; } break; case id_SPIN_BEFORE_SPACING: case id_SPIN_AFTER_SPACING: dimSpin = DIM_PT; dSpinUnit = 6.0; dMin = 0.0; bMin = true; break; case id_SPIN_SPECIAL_SPACING: switch(_getMenuItemValue(id_MENU_SPECIAL_SPACING)) { case spacing_SINGLE: case spacing_ONEANDHALF: case spacing_DOUBLE: _setMenuItemValue(id_MENU_SPECIAL_SPACING, spacing_MULTIPLE); // fall through case spacing_MULTIPLE: dimSpin = DIM_none; dSpinUnit = 0.1; dMin = 0.5; bMin = true; break; case spacing_EXACTLY: dMin = 1; // fall through case spacing_ATLEAST: dimSpin = DIM_PT; dSpinUnit = SPIN_INCR_PT; bMin = true; break; default: UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); break; } break; default: UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); break; } // figure out spin precision, too const char * szPrecision = ".1"; if ((dimSpin == DIM_PT) || (dimSpin == DIM_PI)) szPrecision = ".0"; // if needed, switch unit systems and round off UT_Dimension dimOld = UT_determineDimension(szOld, dimSpin); if (dimOld != dimSpin) { double dInches = UT_convertToInches(szOld); d = UT_convertInchesToDimension(dInches, dimSpin); } // value is now in desired units, so change it d += (dSpinUnit * amt); if (bMin) { // some spinners clamp at bottom of range if (d < dMin) d = dMin; } const gchar* szNew = UT_formatDimensionString(dimSpin, d, szPrecision); _setSpinItemValue(edit, szNew); }
bool AP_Dialog_Paragraph::setDialogData(const gchar ** pProps) { UT_return_val_if_fail (pProps, false); // NOTICE : When setting values, this function always calls // NOTICE : _set[thing]ItemValue() with the bToggleDirty flag // NOTICE : set to false, because these are the "un-dirty" // NOTICE : values. if (pProps[0]) { const gchar * sz; sz = UT_getAttribute("text-align", pProps); if (sz) { tAlignState t = align_LEFT; if (strcmp(sz, "center") == 0) t = align_CENTERED; else if (strcmp(sz, "right") == 0) t = align_RIGHT; else if (strcmp(sz, "justify") == 0) t = align_JUSTIFIED; else if (strcmp(sz, "left") == 0) t = align_LEFT; else UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); _setMenuItemValue(id_MENU_ALIGNMENT, t, op_INIT); } sz = UT_getAttribute("dom-dir", pProps); if (sz) { tCheckState t = check_FALSE; if (strcmp(sz, "ltr") == 0) t = check_FALSE; else if (strcmp(sz, "rtl") == 0) t = check_TRUE; else UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); _setCheckItemValue(id_CHECK_DOMDIRECTION, t, op_INIT); } sz = UT_getAttribute("margin-left", pProps); if (sz) _setSpinItemValue(id_SPIN_LEFT_INDENT, sz, op_INIT); sz = UT_getAttribute("margin-right", pProps); if (sz) _setSpinItemValue(id_SPIN_RIGHT_INDENT, sz, op_INIT); sz = UT_getAttribute("text-indent", pProps); if (sz) { // NOTE : Calling UT_convertDimensionless() _discards_ all // NOTE : unit system information. IFF all units are // NOTE : consistent among all paragraph properties will // NOTE : the comparisons be valid. For now this should be // NOTE : valid. if (UT_convertDimensionless(sz) > (double) 0) { // if text-indent is greater than margin-left, we have a "first line" case _setMenuItemValue(id_MENU_SPECIAL_INDENT, indent_FIRSTLINE, op_INIT); } else if (UT_convertDimensionless(sz) < (double) 0) { // if text-indent is less than margin-left, we have a "hanging" case _setMenuItemValue(id_MENU_SPECIAL_INDENT, indent_HANGING, op_INIT); } else { // they're equal then there's nothing special about them _setMenuItemValue(id_MENU_SPECIAL_INDENT, indent_NONE, op_INIT); } // set the value regardless; dialog will enable/disable field // if spacing is "NONE". Must flip the sign (strip minus) // to give illusion of Word's definitions of indent/margin. const gchar * newSz = sz; if (sz[0] == '-') newSz++; _setSpinItemValue(id_SPIN_SPECIAL_INDENT, newSz, op_INIT); } sz = UT_getAttribute("line-height", pProps); if (sz) { UT_uint32 nLen = strlen(sz); if (nLen > 0) { const char * pPlusFound = strrchr(sz, '+'); if (pPlusFound && *(pPlusFound + 1) == 0) { _setMenuItemValue(id_MENU_SPECIAL_SPACING, spacing_ATLEAST, op_INIT); // need to strip off that plus int posPlus = pPlusFound - (char*) sz; UT_return_val_if_fail (posPlus>=0, false); UT_return_val_if_fail (posPlus<100, false); char pTmp[100]; strcpy(pTmp, sz); pTmp[posPlus] = 0; _setSpinItemValue(id_SPIN_SPECIAL_SPACING, (gchar*)pTmp, op_INIT); } else { if(UT_hasDimensionComponent(sz)) _setMenuItemValue(id_MENU_SPECIAL_SPACING, spacing_EXACTLY, op_INIT); //see Bug 10086 for fabs() usage else if((strcmp("1.0", sz) == 0) || (fabs(UT_convertDimensionless(sz) - (double) 1.0) < 1.0e-7)) _setMenuItemValue(id_MENU_SPECIAL_SPACING, spacing_SINGLE, op_INIT); else if((strcmp("1.5", sz) == 0) || (fabs(UT_convertDimensionless(sz) - (double) 1.5) < 1.0e-7)) _setMenuItemValue(id_MENU_SPECIAL_SPACING, spacing_ONEANDHALF, op_INIT); else if((strcmp("2.0", sz) == 0) || (fabs(UT_convertDimensionless(sz) - (double) 2.0) < 1.0e-7)) _setMenuItemValue(id_MENU_SPECIAL_SPACING, spacing_DOUBLE, op_INIT); else _setMenuItemValue(id_MENU_SPECIAL_SPACING, spacing_MULTIPLE, op_INIT); // set the spin contents regardless of menu content; platforms will // enable or disable the spin item for varying states of menu _setSpinItemValue(id_SPIN_SPECIAL_SPACING, sz, op_INIT); } } } sz = UT_getAttribute("margin-top", pProps); if (sz) _setSpinItemValue(id_SPIN_BEFORE_SPACING, sz, op_INIT); sz = UT_getAttribute("margin-bottom", pProps); if (sz) _setSpinItemValue(id_SPIN_AFTER_SPACING, sz, op_INIT); { // NOTE : "orphans" and "widows" hold a number specifying the number // NOTE : of lines to consider an orphaned or widowed piece of text. // NOTE : If they're both 0 they're off. If either is greater than // NOTE : 0, then some form of control is in effect. If the property // NOTE : is not set, they're indeterminate (e.g. because we're setting // NOTE : properties for text with multiple "orphans" values), or because // NOTE : the block has no value for orphans/widows here. bool bNoOrphans = false; bool bNoWidows = false; double orphans = 0, widows = 0; sz = UT_getAttribute("orphans", pProps); if (sz) orphans = UT_convertDimensionless(sz); else bNoOrphans = true; sz = UT_getAttribute("widows", pProps); if (sz) widows = UT_convertDimensionless(sz); else bNoWidows = true; if (bNoOrphans && bNoWidows) _setCheckItemValue(id_CHECK_WIDOW_ORPHAN, check_INDETERMINATE, op_INIT); else if (orphans > 0 || widows > 0) _setCheckItemValue(id_CHECK_WIDOW_ORPHAN, check_TRUE, op_INIT); else _setCheckItemValue(id_CHECK_WIDOW_ORPHAN, check_FALSE, op_INIT); } sz = UT_getAttribute("keep-together", pProps); if (sz) { if (strcmp(sz, "yes") == 0) _setCheckItemValue(id_CHECK_KEEP_LINES, check_TRUE, op_INIT); else _setCheckItemValue(id_CHECK_KEEP_LINES, check_FALSE, op_INIT); } else _setCheckItemValue(id_CHECK_KEEP_LINES, check_INDETERMINATE, op_INIT); sz = UT_getAttribute("keep-with-next", pProps); if (sz) { if (strcmp(sz, "yes") == 0) _setCheckItemValue(id_CHECK_KEEP_NEXT, check_TRUE, op_INIT); else _setCheckItemValue(id_CHECK_KEEP_NEXT, check_FALSE, op_INIT); } else _setCheckItemValue(id_CHECK_KEEP_NEXT, check_INDETERMINATE, op_INIT); // these are not like the others, they set fields on this, not dialogData. sz = UT_getAttribute("page-margin-left", pProps); if (sz) { m_pageLeftMargin = g_strdup(sz); } else { m_pageLeftMargin = g_strdup(PP_lookupProperty("page-margin-left")->getInitial()); } sz = UT_getAttribute("page-margin-right", pProps); if (sz) { m_pageRightMargin = g_strdup(sz); } else { m_pageRightMargin = g_strdup(PP_lookupProperty("page-margin-right")->getInitial()); } // TODO : add these to PP_Property (pp_Property.cpp) !!! // TODO : and to FV_View::getBlockFormat (or else they won't come in) /* m_pageBreakBefore; m_suppressLineNumbers; m_noHyphenate; */ } return true; }