void AP_Dialog_Paragraph::_setSpinItemValue(tControl item, const gchar * value,
											tOperation op /* = op_UICHANGE */)
{
	UT_return_if_fail (item <= m_vecProperties.getItemCount() && value);

	sControlData * pItem = _getPropertyItem (item);
	UT_return_if_fail (pItem);

	// some spinbuttons have special data requirements
	switch(item)
	{
	case id_SPIN_LEFT_INDENT:
	case id_SPIN_RIGHT_INDENT:
	case id_SPIN_SPECIAL_INDENT:
		pItem->setData (reinterpret_cast<const gchar *>(UT_reformatDimensionString (m_dim, value)));
		break;

	case id_SPIN_BEFORE_SPACING:
	case id_SPIN_AFTER_SPACING:
		{
			/* NOTE : line spacing can't be negative, so take absolute value:
			 */
			const char * abs_value = UT_reformatDimensionString (DIM_PT, _makeAbsolute (value));
			pItem->setData (reinterpret_cast<const gchar *>(abs_value));
		}
		break;

	case id_SPIN_SPECIAL_SPACING:
		if (_getMenuItemValue (id_MENU_SPECIAL_SPACING) == spacing_MULTIPLE)
			{
				const char * abs_value = UT_reformatDimensionString (DIM_none, _makeAbsolute (value), ".2");
				pItem->setData (reinterpret_cast<const gchar *>(abs_value));
			}
		else
			{
				const char * abs_value = UT_reformatDimensionString (DIM_PT, _makeAbsolute (value));
				pItem->setData (reinterpret_cast<const gchar *>(abs_value));
			}
		break;

	default:
		/* all others get a simple string copy to the static member
		 */
		pItem->setData (value);
	}

	if ((op == op_UICHANGE) || (op == op_SYNC))
		pItem->changed (true);

	// for UI-driven changes, may need to sync other controls
	if (op == op_UICHANGE)
		_syncControls(item);
}
void AP_Dialog_Paragraph::_setCheckItemValue(tControl item, tCheckState value,
											tOperation op /* = op_UICHANGE */)
{
	UT_return_if_fail (item <= m_vecProperties.getItemCount());

	sControlData * pItem = _getPropertyItem (item);
	UT_return_if_fail (pItem);

	pItem->setData (value);

	if ((op == op_UICHANGE) || (op == op_SYNC))
		pItem->changed (true);

	// for UI-driven changes, may need to sync other controls
	if (op == op_UICHANGE)
		_syncControls(item);
}
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_UnixDialog_Paragraph::runModal(XAP_Frame * pFrame)
{
	m_pFrame = pFrame;

	// Build the window's widgets and arrange them
	GtkWidget * mainWindow = _constructWindow();
	UT_ASSERT(mainWindow);

	// Populate the window's data items
	_populateWindowData();

	// Attach signals (after data settings, so we don't trigger
	// updates yet)
	_connectCallbackSignals();

	// Show the top level dialog,
	gtk_widget_show(mainWindow);

#if defined(EMBEDDED_TARGET) && EMBEDDED_TARGET == EMBEDDED_TARGET_HILDON
#else
	// *** this is how we add the gc ***
	{
		// attach a new graphics context to the drawing area
		UT_ASSERT(m_drawingareaPreview && gtk_widget_get_window(m_drawingareaPreview));

		// make a new Unix GC
		GR_UnixCairoAllocInfo ai(m_drawingareaPreview);
		m_unixGraphics =
		    (GR_CairoGraphics*) XAP_App::getApp()->newGraphics(ai);

		// let the widget materialize
		GtkAllocation allocation;
		gtk_widget_get_allocation(m_drawingareaPreview, &allocation);
		_createPreviewFromGC(m_unixGraphics,
							 (UT_uint32) allocation.width,
							 (UT_uint32) allocation.height);
	}

	// sync all controls once to get started
	// HACK: the first arg gets ignored
	_syncControls(id_MENU_ALIGNMENT, true);
#endif

	bool tabs;
	do {
		switch(abiRunModalDialog(GTK_DIALOG(mainWindow), pFrame, this, BUTTON_CANCEL, false))
		{
		case BUTTON_OK:
		  event_OK(); 
		  tabs = false;
		  break;
		case BUTTON_TABS:
		  event_Tabs ();
		  tabs = true;
		  break;
		default:
		  event_Cancel();
		  tabs = false;
		  break;
		}
	} while (tabs);
	
	abiDestroyWidget(mainWindow);
}
BOOL AP_Win32Dialog_Paragraph::_onInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
	const XAP_StringSet * pSS = m_pApp->getStringSet();

	setDialogTitle (pSS->getValue(AP_STRING_ID_DLG_Para_ParaTitle));

	// localize controls
	_DSX(PARA_BTN_OK,			DLG_OK);
	_DSX(PARA_BTN_CANCEL,		DLG_Cancel);

	_DS(PARA_BTN_TABS,			DLG_Para_ButtonTabs);

	// setup the tabs
	{
		TabParam tp;
		TCITEMW tie;

		XAP_Win32App * pWin32App = static_cast<XAP_Win32App *>(m_pApp);
		HINSTANCE hinst = pWin32App->getInstance();
		DLGTEMPLATE * pTemplate = NULL;
		HWND w = NULL;

		tp.pThis = this;

		// remember the windows we're using

		m_hwndDlg = hWnd;
		m_hwndTab = GetDlgItem(hWnd, AP_RID_DIALOG_PARA_TAB);

		// add a tab for each of the child dialog boxes

		UT_Win32LocaleString str;

		tie.mask = TCIF_TEXT | TCIF_IMAGE | TCIF_PARAM;
		tie.iImage = -1;
		str.fromUTF8(_GV(DLG_Para_TabLabelIndentsAndSpacing));
		tie.pszText = (LPWSTR)str.c_str();
		tie.lParam = AP_RID_DIALOG_PARA_TAB1;
		SendMessageW(m_hwndTab, TCM_INSERTITEMW, 0, (LPARAM)&tie);
		str.fromUTF8(_GV(DLG_Para_TabLabelLineAndPageBreaks));
		tie.pszText = (LPWSTR)str.c_str();
		tie.lParam = AP_RID_DIALOG_PARA_TAB2;
		SendMessageW(m_hwndTab, TCM_INSERTITEMW, 1, (LPARAM)&tie);

		// finally, create the (modeless) child dialogs

		tp.which = AP_RID_DIALOG_PARA_TAB1;
		pTemplate = UT_LockDlgRes(hinst, MAKEINTRESOURCEW(tp.which));
		w = CreateDialogIndirectParamW(hinst, pTemplate, m_hwndTab,
										(DLGPROC)s_tabProc, (LPARAM)&tp);
		UT_ASSERT_HARMLESS((w && (w == m_hwndSpacing)));

		tp.which = AP_RID_DIALOG_PARA_TAB2;
		pTemplate = UT_LockDlgRes(hinst, MAKEINTRESOURCEW(tp.which));
		w = CreateDialogIndirectParamW(hinst, pTemplate, m_hwndTab,
										(DLGPROC)s_tabProc, (LPARAM)&tp);
		UT_ASSERT_HARMLESS((w && (w == m_hwndBreaks)));
	}

	// HACK: make sure the first tab is visible
	// TODO: trigger selchange logic instead
	ShowWindow(m_hwndSpacing, SW_SHOW);

	// sync all controls once to get started
	// HACK: the first arg gets ignored
	_syncControls(id_MENU_ALIGNMENT, true);
	centerDialog();
	return 1;							// 1 == we did not call SetFocus()
}