Author: rpmcruz Date: Thu Dec 20 21:46:07 2007 New Revision: 43217 URL: http://svn.opensuse.org/viewcvs/yast?rev=43217&view=rev Log: Moving unstable-libyui to main. Added: trunk/gtk/src/YGInputField.cc trunk/gtk/src/YGSelectionModel.cc trunk/gtk/src/YGSelectionModel.h trunk/gtk/src/ygtkcellrenderertextpixbuf.c trunk/gtk/src/ygtkcellrenderertextpixbuf.h trunk/gtk/src/ygtkscrolledwindow.c trunk/gtk/src/ygtkscrolledwindow.h trunk/gtk/src/ygtktogglebutton.c trunk/gtk/src/ygtktogglebutton.h Added: trunk/gtk/src/YGInputField.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGInputField.cc?rev=43217... ============================================================================== --- trunk/gtk/src/YGInputField.cc (added) +++ trunk/gtk/src/YGInputField.cc Thu Dec 20 21:46:07 2007 @@ -0,0 +1,284 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +#include <config.h> +#include <ycp/y2log.h> +#include <YGUI.h> +#include "YInputField.h" +#include "YGWidget.h" +#include "YGUtils.h" +#include "ygtkfieldentry.h" + +class YGInputField : public YInputField, public YGLabeledWidget +{ +public: + YGInputField (YWidget *parent, const string &label, bool passwordMode) + : YInputField (NULL, label, passwordMode), + YGLabeledWidget (this, parent, label, YD_HORIZ, true, + YGTK_TYPE_FIELD_ENTRY, NULL) + { + YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget()); + ygtk_field_entry_add_field (field, 0); + + GtkEntry *entry = ygtk_field_entry_get_field_widget (field, 0); + gtk_entry_set_activates_default (entry, TRUE); + if (passwordMode) + gtk_entry_set_visibility (entry, FALSE); + + g_signal_connect (G_OBJECT (getWidget()), "field-entry-changed", + G_CALLBACK (value_changed_cb), this); + } + + // YInputField + virtual string value() + { + YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget()); + return ygtk_field_entry_get_field_text (field, 0); + } + + virtual void setValue (const string &text) + { + YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget()); + ygtk_field_entry_set_field_text (field, 0, text.c_str()); + } + + void updateProps() + { + YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget()); + ygtk_field_entry_setup_field (field, 0, inputMaxLength(), validChars().c_str()); + } + + virtual void setInputMaxLength (int len) + { + YInputField::setInputMaxLength (len); + updateProps(); + } + + virtual void setValidChars (const string &validChars) + { + YInputField::setValidChars (validChars); + updateProps(); + } + + static void value_changed_cb (YGtkFieldEntry *entry, gint field_nb, YGInputField *pThis) + { + pThis->emitEvent (YEvent::ValueChanged); + } + + YGWIDGET_IMPL_COMMON + YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YInputField) +}; + +YInputField *YGWidgetFactory::createInputField (YWidget *parent, const string &label, + bool passwordMode) +{ + return new YGInputField (parent, label, passwordMode); +} + +#include "YTimeField.h" + +class YGTimeField : public YTimeField, public YGLabeledWidget +{ +public: + YGTimeField (YWidget *parent, const string &label) + : YTimeField (NULL, label), + YGLabeledWidget (this, parent, label, YD_HORIZ, true, + YGTK_TYPE_FIELD_ENTRY, NULL) + { + IMPL + YGtkFieldEntry *field = YGTK_FIELD_ENTRY (getWidget()); + ygtk_field_entry_add_field (field, ':'); + ygtk_field_entry_add_field (field, ':'); + ygtk_field_entry_setup_field (field, 0, 2, "0123456789"); + ygtk_field_entry_setup_field (field, 1, 2, "0123456789"); + + g_signal_connect (G_OBJECT (getWidget()), "field-entry-changed", + G_CALLBACK (value_changed_cb), this); + } + + // YTimeField + virtual void setValue (const string &time) + { + IMPL + char hours[3], mins[3]; + sscanf (time.c_str(), "%2s:%2s", hours, mins); + + YGtkFieldEntry *entry = YGTK_FIELD_ENTRY (getWidget()); + ygtk_field_entry_set_field_text (entry, 0, hours); + ygtk_field_entry_set_field_text (entry, 1, mins); + } + + virtual string value() + { + IMPL + const gchar *hours, *mins; + YGtkFieldEntry *entry = YGTK_FIELD_ENTRY (getWidget()); + hours = ygtk_field_entry_get_field_text (entry, 0); + mins = ygtk_field_entry_get_field_text (entry, 1); + + gchar *time = g_strdup_printf ("%02d:%02d:00", atoi (hours), atoi (mins)); + string str (time); + g_free (time); + return str; + } + + // callbacks + static void value_changed_cb (YGtkFieldEntry *entry, gint field_nb, + YGTimeField *pThis) + { IMPL; pThis->emitEvent (YEvent::ValueChanged); } + + YGWIDGET_IMPL_COMMON + YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YTimeField) +}; + +YTimeField *YGOptionalWidgetFactory::createTimeField (YWidget *parent, const string &label) +{ + IMPL + return new YGTimeField (parent, label); +} + +#include "YDateField.h" +#include "ygtkmenubutton.h" + +class YGDateField : public YDateField, public YGLabeledWidget +{ +GtkWidget *m_calendar, *m_popup_calendar; + +public: + YGDateField (YWidget *parent, const string &label) + : YDateField (NULL, label), + YGLabeledWidget (this, parent, label, YD_HORIZ, true, YGTK_TYPE_FIELD_ENTRY, NULL) + { + IMPL + ygtk_field_entry_add_field (getField(), '-'); + ygtk_field_entry_add_field (getField(), '-'); + ygtk_field_entry_add_field (getField(), '-'); + ygtk_field_entry_setup_field (getField(), 0, 4, "0123456789"); + ygtk_field_entry_setup_field (getField(), 1, 2, "0123456789"); + ygtk_field_entry_setup_field (getField(), 2, 2, "0123456789"); + + m_calendar = gtk_calendar_new(); + gtk_widget_show (m_calendar); + GtkWidget *popup = ygtk_popup_window_new (m_calendar); + + GtkWidget *menu_button = ygtk_menu_button_new(); + ygtk_menu_button_set_popup (YGTK_MENU_BUTTON (menu_button), popup); + gtk_widget_show (menu_button); + gtk_box_pack_start (GTK_BOX (getWidget()), menu_button, FALSE, TRUE, 6); + + g_signal_connect (G_OBJECT (getField()), "field-entry-changed", + G_CALLBACK (value_changed_cb), this); + + g_signal_connect (G_OBJECT (m_calendar), "day-selected", + G_CALLBACK (calendar_changed_cb), this); + g_signal_connect (G_OBJECT (m_calendar), "day-selected-double-click", + G_CALLBACK (double_click_cb), popup); + } + + inline GtkCalendar *getCalendar() + { return GTK_CALENDAR (m_calendar); } + inline YGtkFieldEntry *getField() + { return YGTK_FIELD_ENTRY (getWidget()); } + + // YDateField + virtual void setValue (const string &date) + { + IMPL + char year[5], month[3], day[3]; + sscanf (date.c_str(), "%4s-%2s-%2s", year, month, day); + + gtk_calendar_select_month (getCalendar(), atoi (month)-1, atoi (year)); + gtk_calendar_select_day (getCalendar(), atoi (day)); + + ygtk_field_entry_set_field_text (getField(), 0, year); + ygtk_field_entry_set_field_text (getField(), 1, month); + ygtk_field_entry_set_field_text (getField(), 2, day); + } + + virtual string value() + { + IMPL + const gchar *year, *month, *day; + year = ygtk_field_entry_get_field_text (getField(), 0); + month = ygtk_field_entry_get_field_text (getField(), 1); + day = ygtk_field_entry_get_field_text (getField(), 2); + + gchar *time = g_strdup_printf ("%04d-%02d-%02d", atoi (year), + atoi (month), atoi (day)); + string str (time); + g_free (time); + return str; + } + + // callbacks + static void value_changed_cb (YGtkFieldEntry *entry, gint field_nb, + YGDateField *pThis) + { + IMPL + int year, month, day; + year = atoi (ygtk_field_entry_get_field_text (pThis->getField(), 0)); + month = atoi (ygtk_field_entry_get_field_text (pThis->getField(), 1)); + day = atoi (ygtk_field_entry_get_field_text (pThis->getField(), 2)); + + if (day < 1 || day > 31 || month < 1 || month > 12) + return; // avoid GtkCalendar warnings + + g_signal_handlers_block_by_func (pThis->getCalendar(), + (gpointer) calendar_changed_cb, pThis); + + gtk_calendar_select_month (pThis->getCalendar(), month-1, year); + gtk_calendar_select_day (pThis->getCalendar(), day); + + g_signal_handlers_unblock_by_func (pThis->getCalendar(), + (gpointer) calendar_changed_cb, pThis); + + pThis->emitEvent (YEvent::ValueChanged); + } + + static void calendar_changed_cb (GtkCalendar *calendar, YGDateField *pThis) + { + IMPL + guint year, month, day; + gtk_calendar_get_date (calendar, &year, &month, &day); + month += 1; // GTK calendar months go from 0 to 11 + + gchar *year_str, *month_str, *day_str; + year_str = g_strdup_printf ("%d", year); + month_str = g_strdup_printf ("%d", month); + day_str = g_strdup_printf ("%d", day); + + g_signal_handlers_block_by_func (pThis->getField(), + (gpointer) value_changed_cb, pThis); + + YGtkFieldEntry *entry = pThis->getField(); + ygtk_field_entry_set_field_text (entry, 0, year_str); + ygtk_field_entry_set_field_text (entry, 1, month_str); + ygtk_field_entry_set_field_text (entry, 2, day_str); + + g_signal_handlers_unblock_by_func (pThis->getField(), + (gpointer) value_changed_cb, pThis); + + g_free (year_str); + g_free (month_str); + g_free (day_str); + + pThis->emitEvent (YEvent::ValueChanged); + } + + static void double_click_cb (GtkCalendar *calendar, YGtkPopupWindow *popup) + { + // close popup + gtk_widget_hide (GTK_WIDGET (popup)); + } + + YGWIDGET_IMPL_COMMON + YGLABEL_WIDGET_IMPL_SET_LABEL_CHAIN (YDateField) +}; + +YDateField *YGOptionalWidgetFactory::createDateField (YWidget *parent, const string &label) +{ + IMPL + return new YGDateField (parent, label); +} + Added: trunk/gtk/src/YGSelectionModel.cc URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGSelectionModel.cc?rev=4... ============================================================================== --- trunk/gtk/src/YGSelectionModel.cc (added) +++ trunk/gtk/src/YGSelectionModel.cc Thu Dec 20 21:46:07 2007 @@ -0,0 +1,179 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +#include <config.h> +#include <ycp/y2log.h> +#include <gtk/gtk.h> +#include <YTreeItem.h> +#include "YGSelectionModel.h" +#include "YGUtils.h" + +YGSelectionModel::YGSelectionModel (YSelectionWidget *ywidget, bool ordinaryModel, bool isTree) + : isTree (isTree), ywidget (ywidget) +{ + if (ordinaryModel) { + vector <GType> cols; + cols.push_back (G_TYPE_STRING); + cols.push_back (GDK_TYPE_PIXBUF); + createModel (cols); + } +} + +YGSelectionModel::~YGSelectionModel() +{ g_object_unref (G_OBJECT (m_model)); } + +void YGSelectionModel::createModel (const vector <GType> &types) +{ + int colsNb = types.size()+1; + GType types_array [colsNb]; + int i = 0; + for (vector <GType>::const_iterator it = types.begin(); it != types.end(); it++) + types_array [i++] = *it; + types_array[colsNb-1] = G_TYPE_POINTER; + + if (isTree) + m_model = GTK_TREE_MODEL (gtk_tree_store_newv (colsNb, types_array)); + else + m_model = GTK_TREE_MODEL (gtk_list_store_newv (colsNb, types_array)); +} + +GtkTreeModel *YGSelectionModel::getModel() +{ return m_model; } +GtkListStore *YGSelectionModel::getListStore() +{ return m_model ? GTK_LIST_STORE (m_model) : NULL; } +GtkTreeStore *YGSelectionModel::getTreeStore() +{ return m_model ? GTK_TREE_STORE (m_model) : NULL; } + +bool YGSelectionModel::isEmpty() +{ + GtkTreeIter iter; + return !gtk_tree_model_get_iter_first (getModel(), &iter); +} + +void YGSelectionModel::doAddItem (YItem *item) +{ + GtkTreeIter iter; + addRow (&iter, item); + setCellLabel (&iter, LABEL_COLUMN, item->label()); + setCellIcon (&iter, ICON_COLUMN, item->iconName()); + for (YItemIterator it = item->childrenBegin(); it != item->childrenEnd(); it++) + doAddItem (*it); +} + +void YGSelectionModel::doDeleteAllItems() +{ + if (isTree) + gtk_tree_store_clear (getTreeStore()); + else + gtk_list_store_clear (getListStore()); +} + +YItem *YGSelectionModel::getItem (GtkTreeIter *iter) +{ + gpointer ptr; + gtk_tree_model_get (getModel(), iter, getPtrCol(), &ptr, -1); + return (YItem *) ptr; +} + +bool YGSelectionModel::getIter (YItem *item, GtkTreeIter *iter) +{ + if (!item) + return false; + GtkTreePath *path = gtk_tree_path_new(); + for (; item; item = item->parent()) { + int index = GPOINTER_TO_INT (item->data()); + gtk_tree_path_prepend_index (path, index); + } + + bool ret = gtk_tree_model_get_iter (getModel(), iter, path); + gtk_tree_path_free (path); + return ret; +} + +void YGSelectionModel::implFocusItem (YItem *item) +{ + GtkTreeIter iter; + if (getIter (item, &iter)) + setFocusItem (&iter, false); +} + +int YGSelectionModel::getPtrCol() +{ + return gtk_tree_model_get_n_columns (getModel()) - 1; +} + +void YGSelectionModel::addRow (GtkTreeIter *iter, YItem *item) +{ + struct inner { + static void setItemData (GtkTreeModel *model, GtkTreeIter *iter, YItem *item) + { + int index; + GtkTreePath *path = gtk_tree_model_get_path (model, iter); + + int depth = gtk_tree_path_get_depth (path); + int *path_int = gtk_tree_path_get_indices (path); + g_assert (path_int != NULL); + index = path_int [depth-1]; + + gtk_tree_path_free (path); + g_assert (index != -1); + item->setData (GINT_TO_POINTER (index)); + } + }; + + bool empty = isEmpty(); + + if (isTree) { + GtkTreeStore *store = getTreeStore(); + if (item->parent()) { + GtkTreeIter parent; + getIter (item->parent(), &parent); + gtk_tree_store_append (store, iter, &parent); + } + else + gtk_tree_store_append (store, iter, NULL); + gtk_tree_store_set (store, iter, getPtrCol(), item, -1); + inner::setItemData (getModel(), iter, item); + + YTreeItem *tree_item = dynamic_cast <YTreeItem *> (item); + if (tree_item && tree_item->isOpen()) + expand (iter); + } + else { + GtkListStore *store = getListStore(); + gtk_list_store_append (store, iter); + gtk_list_store_set (store, iter, getPtrCol(), item, -1); + inner::setItemData (getModel(), iter, item); + } + + if (item->selected() || empty) + setFocusItem (iter, true); +} + +void YGSelectionModel::setCellLabel (GtkTreeIter *iter, int col, const string &label) +{ + if (isTree) + gtk_tree_store_set (getTreeStore(), iter, col, label.c_str(), -1); + else + gtk_list_store_set (getListStore(), iter, col, label.c_str(), -1); +} + +void YGSelectionModel::setCellIcon (GtkTreeIter *iter, int col, const string &icon) +{ + string path = ywidget->iconFullPath (icon); + GdkPixbuf *pixbuf = YGUtils::loadPixbuf (path.c_str()); + if (isTree) + gtk_tree_store_set (getTreeStore(), iter, col, pixbuf, -1); + else + gtk_list_store_set (getListStore(), iter, col, pixbuf, -1); +} + +void YGSelectionModel::setCellToggle (GtkTreeIter *iter, int col, bool select) +{ + if (isTree) + gtk_tree_store_set (getTreeStore(), iter, col, select, -1); + else + gtk_list_store_set (getListStore(), iter, col, select, -1); +} + Added: trunk/gtk/src/YGSelectionModel.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/YGSelectionModel.h?rev=43... ============================================================================== --- trunk/gtk/src/YGSelectionModel.h (added) +++ trunk/gtk/src/YGSelectionModel.h Thu Dec 20 21:46:07 2007 @@ -0,0 +1,92 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +/* Builds a model for the given YItems to be used by YSelectedWidgets. */ + +#ifndef YGSELECTION_MODEL_H +#define YGSELECTION_MODEL_H + +#include <YItem.h> +#include <YSelectionWidget.h> +#include <gtk/gtktreemodel.h> +#include <gtk/gtkliststore.h> +#include <gtk/gtktreestore.h> + +struct YGSelectionModel +{ + // ordinary model columns + enum ColumnIndex { + LABEL_COLUMN, ICON_COLUMN + }; + + YGSelectionModel (YSelectionWidget *ywidget, bool ordinaryModel, bool isTree); + virtual ~YGSelectionModel(); + + GtkTreeModel *getModel(); + void createModel (const vector <GType> &types); + + void doAddItem (YItem *item); + void doDeleteAllItems(); + + virtual YItem *focusItem() = 0; + virtual void setFocusItem (GtkTreeIter *iter, bool addingRow) = 0; + virtual void unsetFocus() = 0; + + // to be implemented by trees + virtual void expand (GtkTreeIter *iter) {} + + YItem *getItem (GtkTreeIter *iter); + bool getIter (YItem *item, GtkTreeIter *iter); + + void addRow (GtkTreeIter *iter, YItem *item); + void setCellLabel (GtkTreeIter *iter, int col, const string &label); + void setCellIcon (GtkTreeIter *iter, int col, const string &icon); + void setCellToggle (GtkTreeIter *iter, int col, bool selected); + + int getPtrCol(); + +protected: + void implFocusItem (YItem *item); +private: + GtkTreeModel *m_model; + bool isTree; + GtkListStore *getListStore(); + GtkTreeStore *getTreeStore(); + bool isEmpty(); + YSelectionWidget *ywidget; // we use it, to get the path for icons +}; + +#define YGSELECTION_WIDGET_IMPL_ADD(ParentClass) \ + virtual void addItem(YItem *item) { \ + ParentClass::addItem (item); \ + doAddItem (item); \ + } + +#define YGSELECTION_WIDGET_IMPL_CLEAR(ParentClass) \ + virtual void deleteAllItems() { \ + doDeleteAllItems(); \ + ParentClass::deleteAllItems(); \ + } + +#define YGSELECTION_WIDGET_IMPL_SELECT(ParentClass) \ + virtual void selectItem (YItem *item, bool select) { \ + if (select) \ + implFocusItem (item); \ + ParentClass::selectItem (item, select); \ + } \ + virtual void deselectAllItems() { \ + unsetFocus(); \ + ParentClass::deselectAllItems(); \ + } \ + virtual YItem *selectedItem() { \ + return focusItem(); \ + } \ + +#define YGSELECTION_WIDGET_IMPL_ALL(ParentClass) \ + YGSELECTION_WIDGET_IMPL_ADD(ParentClass) \ + YGSELECTION_WIDGET_IMPL_CLEAR(ParentClass) \ + YGSELECTION_WIDGET_IMPL_SELECT(ParentClass) + +#endif /*YGSELECTION_MODEL_H*/ + Added: trunk/gtk/src/ygtkcellrenderertextpixbuf.c URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkcellrenderertextpixbu... ============================================================================== --- trunk/gtk/src/ygtkcellrenderertextpixbuf.c (added) +++ trunk/gtk/src/ygtkcellrenderertextpixbuf.c Thu Dec 20 21:46:07 2007 @@ -0,0 +1,216 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +/* YGtkCellRendererTextPixbuf widget */ +// check the header file for information about this widget + +#include <config.h> +#include "ygtkcellrenderertextpixbuf.h" + +#define PIXBUF_TEXT_SPACING 4 + +enum { + PROP_0, + PROP_TEXT, + PROP_PIXBUF +}; + +G_DEFINE_TYPE (YGtkCellRendererTextPixbuf, ygtk_cell_renderer_text_pixbuf, GTK_TYPE_CELL_RENDERER) + +static void ygtk_cell_renderer_text_pixbuf_init (YGtkCellRendererTextPixbuf *tpcell) +{ + GtkCellRenderer *cell = GTK_CELL_RENDERER (tpcell); + cell->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE; + cell->xalign = 0.0; + cell->yalign = 0.5; + cell->xpad = 0; + cell->ypad = 0; + tpcell->text = NULL; + tpcell->pixbuf = NULL; +} + +static void ygtk_cell_renderer_text_pixbuf_finalize (GObject *object) +{ + YGtkCellRendererTextPixbuf *tpcell = YGTK_CELL_RENDERER_TEXT_PIXBUF (object); + if (tpcell->text) { + g_free (tpcell->text); + tpcell->text = NULL; + } + if (tpcell->pixbuf) { + g_object_unref (G_OBJECT (tpcell->pixbuf)); + tpcell->pixbuf = NULL; + } + G_OBJECT_CLASS (ygtk_cell_renderer_text_pixbuf_parent_class)->finalize (object); +} + +static void ygtk_cell_renderer_text_pixbuf_get_property (GObject *object, + guint param_id, GValue *value, GParamSpec *pspec) +{ + YGtkCellRendererTextPixbuf *tpcell = YGTK_CELL_RENDERER_TEXT_PIXBUF (object); + switch (param_id) { + case PROP_TEXT: + g_value_set_string (value, tpcell->text); + break; + case PROP_PIXBUF: + g_value_set_object (value, G_OBJECT (tpcell->pixbuf)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void ygtk_cell_renderer_text_pixbuf_set_property (GObject *object, + guint param_id, const GValue *value, GParamSpec *pspec) +{ + YGtkCellRendererTextPixbuf *tpcell = YGTK_CELL_RENDERER_TEXT_PIXBUF (object); + switch (param_id) { + case PROP_TEXT: + if (tpcell->text) + g_free (tpcell->text); + tpcell->text = g_strdup (g_value_get_string (value)); + break; + case PROP_PIXBUF: + if (tpcell->pixbuf) + g_object_unref (G_OBJECT (tpcell->pixbuf)); + tpcell->pixbuf = (GdkPixbuf *) g_value_dup_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static PangoLayout *create_layout (YGtkCellRendererTextPixbuf *tpcell, GtkWidget *widget) +{ + if (tpcell->text) + return gtk_widget_create_pango_layout (widget, tpcell->text); + return NULL; +} + +static void ygtk_cell_renderer_text_pixbuf_get_size (GtkCellRenderer *cell, + GtkWidget *widget, GdkRectangle *cell_area, gint *xoffset, gint *yoffset, + gint *width, gint *height) +{ + YGtkCellRendererTextPixbuf *tpcell = YGTK_CELL_RENDERER_TEXT_PIXBUF (cell); + + // will be calculated at expose, as both pixbuf and text have their offsets... + if (xoffset) *xoffset = 0; + if (yoffset) *yoffset = 0; + if (!width && !height) + return; + + if (tpcell->pixbuf) { + *width += gdk_pixbuf_get_width (tpcell->pixbuf); + *height = MAX (*height, gdk_pixbuf_get_height (tpcell->pixbuf)); + } + if (tpcell->text) { + if (tpcell->pixbuf) + *width += PIXBUF_TEXT_SPACING; + + PangoLayout *layout = create_layout (tpcell, widget); + int lw, lh; + pango_layout_get_pixel_size (layout, &lw, &lh); + *width += lw; + *height = MAX (*height, lh); + + g_object_unref (G_OBJECT (layout)); + } + + *width += cell->xpad*2; + *height += cell->ypad*2; +} + +static void ygtk_cell_renderer_text_pixbuf_render (GtkCellRenderer *cell, + GdkDrawable *window, GtkWidget *widget, GdkRectangle *background_area, + GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) +{ + YGtkCellRendererTextPixbuf *tpcell = YGTK_CELL_RENDERER_TEXT_PIXBUF (cell); + + GtkStateType state; + // like GtkCellRendererText... + if (!cell->sensitive) + state = GTK_STATE_INSENSITIVE; + else if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) { + gboolean has_focus = GTK_WIDGET_HAS_FOCUS (widget); + state = has_focus ? GTK_STATE_SELECTED : GTK_STATE_ACTIVE; + } + else if ((flags & GTK_CELL_RENDERER_PRELIT) == GTK_CELL_RENDERER_PRELIT && + GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT) { + state = GTK_STATE_PRELIGHT; + } + else { + if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE) + state = GTK_STATE_INSENSITIVE; + else + state = GTK_STATE_NORMAL; + } + + int x = cell_area->x, y = cell_area->y; + + gfloat xalign = cell->xalign, yalign = cell->yalign; + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) + xalign = 1.0 - xalign; + + if (tpcell->pixbuf) { + int w, h; + w = gdk_pixbuf_get_width (tpcell->pixbuf); + h = gdk_pixbuf_get_height (tpcell->pixbuf); + + int xoffset, yoffset; + xoffset = xalign * (cell_area->width - (w + (2*cell->xpad))); + yoffset = yalign * (cell_area->height - (h + (2*cell->ypad))); + + cairo_t *cr = gdk_cairo_create (window); + gdk_cairo_set_source_pixbuf (cr, tpcell->pixbuf, x+xoffset, y+yoffset); + + cairo_rectangle (cr, x+xoffset, y+yoffset, w, h); + cairo_fill (cr); + cairo_destroy (cr); + + x += w + PIXBUF_TEXT_SPACING; + } + + if (tpcell->text) { + PangoLayout *layout = create_layout (tpcell, widget); + + PangoRectangle rect; + pango_layout_get_pixel_extents (layout, NULL, &rect); + + int xoffset, yoffset; + xoffset = xalign * (cell_area->width - (rect.width + (2*cell->xpad))); + yoffset = yalign * (cell_area->height - (rect.height + (2*cell->ypad))); + + GtkStyle *style = gtk_widget_get_style (widget); + gtk_paint_layout (style, window, state, TRUE, expose_area, widget, + "cellrenderertext", x+xoffset, y+yoffset, layout); + + g_object_unref (G_OBJECT (layout)); + } +} + +GtkCellRenderer *ygtk_cell_renderer_text_pixbuf_new (void) +{ + return g_object_new (YGTK_TYPE_CELL_RENDERER_TEXT_PIXBUF, NULL); +} + +static void ygtk_cell_renderer_text_pixbuf_class_init (YGtkCellRendererTextPixbufClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + object_class->get_property = ygtk_cell_renderer_text_pixbuf_get_property; + object_class->set_property = ygtk_cell_renderer_text_pixbuf_set_property; + object_class->finalize = ygtk_cell_renderer_text_pixbuf_finalize; + + GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (class); + cell_class->get_size = ygtk_cell_renderer_text_pixbuf_get_size; + cell_class->render = ygtk_cell_renderer_text_pixbuf_render; + + g_object_class_install_property (object_class, PROP_TEXT, + g_param_spec_string ("text", "Text", "The text", NULL, + G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); + g_object_class_install_property (object_class, PROP_PIXBUF, + g_param_spec_object ("pixbuf", "Image", "Side image", GDK_TYPE_PIXBUF, + G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); +} + Added: trunk/gtk/src/ygtkcellrenderertextpixbuf.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkcellrenderertextpixbu... ============================================================================== --- trunk/gtk/src/ygtkcellrenderertextpixbuf.h (added) +++ trunk/gtk/src/ygtkcellrenderertextpixbuf.h Thu Dec 20 21:46:07 2007 @@ -0,0 +1,47 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +/* YGtkCellRendererTextPixbuf is a combination of GtkCellRendererText and + GtkCellRendererPixbuf. It allows text and icons to be mixed on the same + column. +*/ + +#ifndef YGTK_CELL_RENDERER_TEXT_PIXBUF_H +#define YGTK_CELL_RENDERER_TEXT_PIXBUF_H + +#include <gtk/gtkcellrenderer.h> +G_BEGIN_DECLS + +#define YGTK_TYPE_CELL_RENDERER_TEXT_PIXBUF (ygtk_cell_renderer_text_pixbuf_get_type ()) +#define YGTK_CELL_RENDERER_TEXT_PIXBUF(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + YGTK_TYPE_CELL_RENDERER_TEXT_PIXBUF, YGtkCellRendererTextPixbuf)) +#define YGTK_CELL_RENDERER_TEXT_PIXBUF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \ + YGTK_TYPE_CELL_RENDERER_TEXT_PIXBUF, YGtkCellRendererTextPixbufClass)) +#define YGTK_IS_CELL_RENDERER_TEXT_PIXBUF(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + YGTK_TYPE_CELL_RENDERER_TEXT_PIXBUF)) +#define YGTK_IS_CELL_RENDERER_TEXT_PIXBUF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + YGTK_TYPE_CELL_RENDERER_TEXT_PIXBUF)) +#define YGTK_CELL_RENDERER_TEXT_PIXBUF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + YGTK_TYPE_CELL_RENDERER_TEXT_PIXBUF, YGtkCellRendererTextPixbufClass)) + +typedef struct _YGtkCellRendererTextPixbuf +{ + GtkCellRenderer parent; + + // private: + gchar *text; + GdkPixbuf *pixbuf; +} YGtkCellRendererTextPixbuf; + +typedef struct _YGtkCellRendererTextPixbufClass +{ + GtkCellRendererClass parent_class; +} YGtkCellRendererTextPixbufClass; + +GtkCellRenderer *ygtk_cell_renderer_text_pixbuf_new (void); +GType ygtk_cell_renderer_text_pixbuf_get_type (void) G_GNUC_CONST; + +G_END_DECLS +#endif /*YGTK_CELL_RENDERER_TEXT_PIXBUF_H*/ + Added: trunk/gtk/src/ygtkscrolledwindow.c URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkscrolledwindow.c?rev=... ============================================================================== --- trunk/gtk/src/ygtkscrolledwindow.c (added) +++ trunk/gtk/src/ygtkscrolledwindow.c Thu Dec 20 21:46:07 2007 @@ -0,0 +1,99 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +/* YGtkScrolledWindow widget */ +// check the header file for information about this widget + +#include <config.h> +#include "ygtkscrolledwindow.h" +#include <gtk/gtk.h> + +#define CHILD_SPACING 2 + +G_DEFINE_TYPE (YGtkScrolledWindow, ygtk_scrolled_window, GTK_TYPE_SCROLLED_WINDOW) + +static void ygtk_scrolled_window_init (YGtkScrolledWindow *scroll) +{ + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), + GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN); +} + +static void ygtk_scrolled_window_destroy (GtkObject *object) +{ + GTK_OBJECT_CLASS (ygtk_scrolled_window_parent_class)->destroy (object); + YGtkScrolledWindow *scroll = YGTK_SCROLLED_WINDOW (object); + ygtk_scrolled_window_set_corner_widget (scroll, NULL); +} + +static void ygtk_scrolled_window_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GTK_WIDGET_CLASS (ygtk_scrolled_window_parent_class)->size_allocate + (widget, allocation); + if (!GTK_WIDGET_REALIZED (widget)) + return; + + YGtkScrolledWindow *scroll = YGTK_SCROLLED_WINDOW (widget); + if (scroll->corner_child) { + GtkRequisition req; + gtk_widget_size_request (scroll->corner_child, &req); + + GtkWidget *vbar; + vbar = gtk_scrolled_window_get_vscrollbar (GTK_SCROLLED_WINDOW (scroll)); + + vbar->allocation.height = MAX (0, widget->allocation.height - req.height - CHILD_SPACING); + GtkAllocation alloc = { vbar->allocation.x, + vbar->allocation.y + vbar->allocation.height + CHILD_SPACING, + vbar->allocation.width, + req.height }; + gtk_widget_size_allocate (scroll->corner_child, &alloc); + } +} + +static void ygtk_scrolled_window_forall (GtkContainer *container, + gboolean include_internals, GtkCallback callback, gpointer callback_data) +{ + GTK_CONTAINER_CLASS (ygtk_scrolled_window_parent_class)->forall (container, + include_internals, callback, callback_data); + if (include_internals) { + YGtkScrolledWindow *scroll = YGTK_SCROLLED_WINDOW (container); + if (scroll->corner_child) + callback (scroll->corner_child, callback_data); + } +} + +void ygtk_scrolled_window_set_corner_widget (YGtkScrolledWindow *scroll, GtkWidget *child) +{ + if (scroll->corner_child) + gtk_widget_unparent (scroll->corner_child); + scroll->corner_child = child; + if (child) + gtk_widget_set_parent (child, GTK_WIDGET (scroll)); +} + +void ygtk_scrolled_window_replace (YGtkScrolledWindow *scroll, GtkWidget *child) +{ + GtkWidget *current = gtk_bin_get_child (GTK_BIN (scroll)); + if (current) + gtk_container_remove (GTK_CONTAINER (scroll), current); + if (child) + gtk_container_add (GTK_CONTAINER (scroll), child); +} + +GtkWidget *ygtk_scrolled_window_new (void) +{ return g_object_new (YGTK_TYPE_SCROLLED_WINDOW, NULL); } + +static void ygtk_scrolled_window_class_init (YGtkScrolledWindowClass *klass) +{ + GtkContainerClass *gtkcontainer_class = GTK_CONTAINER_CLASS (klass); + gtkcontainer_class->forall = ygtk_scrolled_window_forall; + + GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass); + gtkwidget_class->size_allocate = ygtk_scrolled_window_size_allocate; + + GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass); + gtkobject_class->destroy = ygtk_scrolled_window_destroy; +} + Added: trunk/gtk/src/ygtkscrolledwindow.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtkscrolledwindow.h?rev=... ============================================================================== --- trunk/gtk/src/ygtkscrolledwindow.h (added) +++ trunk/gtk/src/ygtkscrolledwindow.h Thu Dec 20 21:46:07 2007 @@ -0,0 +1,51 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +/* YGtkScrolledWindow extends GtkScrolledWindow adding the possibility to add + a widget in the corner between the scrollbars, flowing into the vertical + scroll bar (which is why the policy should be ALWAYS for the vertical bar). +*/ + +#ifndef YGTK_SCROLLED_WINDOW_H +#define YGTK_SCROLLED_WINDOW_H + +#include <gtk/gtkscrolledwindow.h> +G_BEGIN_DECLS + +#define YGTK_TYPE_SCROLLED_WINDOW (ygtk_scrolled_window_get_type ()) +#define YGTK_SCROLLED_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + YGTK_TYPE_SCROLLED_WINDOW, YGtkScrolledWindow)) +#define YGTK_SCROLLED_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \ + YGTK_TYPE_SCROLLED_WINDOW, YGtkScrolledWindowClass)) +#define YGTK_IS_SCROLLED_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + YGTK_TYPE_SCROLLED_WINDOW)) +#define YGTK_IS_SCROLLED_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + YGTK_TYPE_SCROLLED_WINDOW)) +#define YGTK_SCROLLED_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + YGTK_TYPE_SCROLLED_WINDOW, YGtkScrolledWindowClass)) + +typedef struct _YGtkScrolledWindow +{ + GtkScrolledWindow parent; + //members: + GtkWidget *corner_child; +} YGtkScrolledWindow; + +typedef struct _YGtkScrolledWindowClass +{ + GtkScrolledWindowClass parent_class; +} YGtkScrolledWindowClass; + +GtkWidget* ygtk_scrolled_window_new (void); +GType ygtk_scrolled_window_get_type (void) G_GNUC_CONST; + +// container_add/remove combo +void ygtk_scrolled_window_replace (YGtkScrolledWindow *scroll, GtkWidget *child); + +void ygtk_scrolled_window_set_corner_widget (YGtkScrolledWindow *scroll, + GtkWidget *widget); + +G_END_DECLS +#endif /*YGTK_SCROLLED_WINDOW_H*/ + Added: trunk/gtk/src/ygtktogglebutton.c URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtktogglebutton.c?rev=43... ============================================================================== --- trunk/gtk/src/ygtktogglebutton.c (added) +++ trunk/gtk/src/ygtktogglebutton.c Thu Dec 20 21:46:07 2007 @@ -0,0 +1,90 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +/* YGtkToggleButton widget */ +// check the header file for information about this widget + +#include <config.h> +#include "ygtktogglebutton.h" +#include <gtk/gtk.h> + +static guint toggle_changed_signal; + +G_DEFINE_TYPE (YGtkToggleButton, ygtk_toggle_button, GTK_TYPE_TOGGLE_BUTTON) + +static void ygtk_toggle_button_init (YGtkToggleButton *button) +{ +} + +static void ygtk_toggle_button_destroy (GtkObject *object) +{ + GTK_OBJECT_CLASS (ygtk_toggle_button_parent_class)->destroy (object); + YGtkToggleButton *button = YGTK_TOGGLE_BUTTON (object); + if (button->group && !button->foreign_group) { + g_slist_free (button->group); + button->group = NULL; + } +} + +static void ygtk_toggle_button_toggled (GtkToggleButton *toggle) +{ + GSList *group = YGTK_TOGGLE_BUTTON (toggle)->group; + + if (gtk_toggle_button_get_active (toggle)) { + // disable any active + GSList *i; + for (i = group; i; i = i->next) { + GtkToggleButton *t = i->data; + if (t->active && t != toggle) { + gtk_toggle_button_set_active (t, FALSE); + break; + } + } + + if (i) { + gint nb = g_slist_index (group, toggle); + g_signal_emit (YGTK_TOGGLE_BUTTON (toggle), toggle_changed_signal, 0, nb); + } + } + else { + // force it to be enabled, if no other is (other could be enabled; eg. when + // this code gets triggered from the previous case). + GSList *i; + for (i = group; i; i = i->next) { + GtkToggleButton *t = i->data; + if (t->active && t != toggle) + break; + } + if (!i) + gtk_toggle_button_set_active (toggle, TRUE); + } +} + +GSList *ygtk_toggle_button_get_group (YGtkToggleButton *button) +{ + return button->group; +} + +GtkWidget *ygtk_toggle_button_new (GSList *group) +{ + YGtkToggleButton *button = g_object_new (YGTK_TYPE_TOGGLE_BUTTON, NULL); + button->group = g_slist_append (group, button); + button->foreign_group = group != NULL; + return (GtkWidget *) button; +} + +static void ygtk_toggle_button_class_init (YGtkToggleButtonClass *klass) +{ + GtkObjectClass *gtkobject_class = GTK_OBJECT_CLASS (klass); + gtkobject_class->destroy = ygtk_toggle_button_destroy; + + GtkToggleButtonClass *gtktogglebutton_class = GTK_TOGGLE_BUTTON_CLASS (klass); + gtktogglebutton_class->toggled = ygtk_toggle_button_toggled; + + toggle_changed_signal = g_signal_new ("toggle-changed", + G_TYPE_FROM_CLASS (G_OBJECT_CLASS (klass)), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (YGtkToggleButtonClass, toggle_changed), NULL, NULL, + g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); +} + Added: trunk/gtk/src/ygtktogglebutton.h URL: http://svn.opensuse.org/viewcvs/yast/trunk/gtk/src/ygtktogglebutton.h?rev=43... ============================================================================== --- trunk/gtk/src/ygtktogglebutton.h (added) +++ trunk/gtk/src/ygtktogglebutton.h Thu Dec 20 21:46:07 2007 @@ -0,0 +1,49 @@ +/******************************************************************** + * YaST2-GTK - http://en.opensuse.org/YaST2-GTK * + ********************************************************************/ + +/* YGtkToggleButton extends GtkToggleButton to add groups, just like GtkRadioButtons. +*/ + +#ifndef YGTK_TOGGLE_BUTTON_H +#define YGTK_TOGGLE_BUTTON_H + +#include <gtk/gtktogglebutton.h> +G_BEGIN_DECLS + +#define YGTK_TYPE_TOGGLE_BUTTON (ygtk_toggle_button_get_type ()) +#define YGTK_TOGGLE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + YGTK_TYPE_TOGGLE_BUTTON, YGtkToggleButton)) +#define YGTK_TOGGLE_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \ + YGTK_TYPE_TOGGLE_BUTTON, YGtkToggleButtonClass)) +#define YGTK_IS_TOGGLE_BUTTON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + YGTK_TYPE_TOGGLE_BUTTON)) +#define YGTK_IS_TOGGLE_BUTTON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + YGTK_TYPE_TOGGLE_BUTTON)) +#define YGTK_TOGGLE_BUTTON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + YGTK_TYPE_TOGGLE_BUTTON, YGtkToggleButtonClass)) + +typedef struct _YGtkToggleButton +{ + GtkToggleButton parent; + // members: + GSList *group; + gboolean foreign_group; // (shouldn't be needed...) +} YGtkToggleButton; + +typedef struct _YGtkToggleButtonClass +{ + GtkToggleButtonClass parent_class; + + // signals: + void (*toggle_changed) (GtkToggleButton *toggle, gint nb); +} YGtkToggleButtonClass; + +GtkWidget* ygtk_toggle_button_new (GSList *group); +GType ygtk_toggle_button_get_type (void) G_GNUC_CONST; + +GSList *ygtk_toggle_button_get_group (YGtkToggleButton *button); + +G_END_DECLS +#endif /*YGTK_TOGGLE_BUTTON_H*/ + -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org