mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-31 19:51:52 +02:00
Update to v094r43 release.
byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
This commit is contained in:
@@ -12,7 +12,7 @@ auto pAction::setEnabled(bool enabled) -> void {
|
||||
gtk_widget_set_sensitive(widget, enabled);
|
||||
}
|
||||
|
||||
auto pAction::setFont(const string& font) -> void {
|
||||
auto pAction::setFont(const Font& font) -> void {
|
||||
pFont::setFont(widget, font);
|
||||
}
|
||||
|
||||
|
@@ -6,7 +6,7 @@ struct pAction : pObject {
|
||||
Declare(Action, Object)
|
||||
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
auto _mnemonic(string text) -> string;
|
||||
|
@@ -9,6 +9,7 @@ static auto MenuItem_activate(GtkMenuItem*, pMenuItem* p) -> void {
|
||||
auto pMenuItem::construct() -> void {
|
||||
widget = gtk_image_menu_item_new_with_mnemonic("");
|
||||
g_signal_connect(G_OBJECT(widget), "activate", G_CALLBACK(MenuItem_activate), (gpointer)this);
|
||||
setImage(state().image);
|
||||
setText(state().text);
|
||||
}
|
||||
|
||||
@@ -16,9 +17,9 @@ auto pMenuItem::destruct() -> void {
|
||||
if(widget) gtk_widget_destroy(widget), widget = nullptr;
|
||||
}
|
||||
|
||||
auto pMenuItem::setIcon(const image& icon) -> void {
|
||||
if(icon) {
|
||||
GtkImage* gtkImage = CreateImage(icon, true);
|
||||
auto pMenuItem::setImage(const Image& image) -> void {
|
||||
if(image) {
|
||||
GtkImage* gtkImage = CreateImage(image, true);
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage);
|
||||
} else {
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr);
|
||||
|
@@ -5,7 +5,7 @@ namespace hiro {
|
||||
struct pMenuItem : pAction {
|
||||
Declare(MenuItem, Action)
|
||||
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
};
|
||||
|
||||
|
@@ -27,8 +27,6 @@ auto pMenuRadioItem::setChecked() -> void {
|
||||
}
|
||||
|
||||
auto pMenuRadioItem::setGroup(sGroup group) -> void {
|
||||
if(!group) return;
|
||||
|
||||
maybe<GtkRadioMenuItem*> gtkRadioMenuItem;
|
||||
for(auto& weak : group->state.objects) {
|
||||
if(auto object = weak.acquire()) {
|
||||
@@ -36,9 +34,13 @@ auto pMenuRadioItem::setGroup(sGroup group) -> void {
|
||||
if(auto self = menuRadioItem->self()) {
|
||||
self->lock();
|
||||
gtk_radio_menu_item_set_group(self->gtkRadioMenuItem, nullptr);
|
||||
if(!gtkRadioMenuItem) gtkRadioMenuItem = self->gtkRadioMenuItem;
|
||||
else gtk_radio_menu_item_set_group(self->gtkRadioMenuItem, gtk_radio_menu_item_get_group(*gtkRadioMenuItem));
|
||||
gtk_check_menu_item_set_active(self->gtkCheckMenuItem, menuRadioItem->checked());
|
||||
if(!gtkRadioMenuItem) {
|
||||
gtkRadioMenuItem = self->gtkRadioMenuItem;
|
||||
gtk_check_menu_item_set_active(self->gtkCheckMenuItem, menuRadioItem->state.checked = true);
|
||||
} else {
|
||||
gtk_radio_menu_item_set_group(self->gtkRadioMenuItem, gtk_radio_menu_item_get_group(*gtkRadioMenuItem));
|
||||
gtk_check_menu_item_set_active(self->gtkCheckMenuItem, menuRadioItem->state.checked = false);
|
||||
}
|
||||
self->unlock();
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ auto pMenu::construct() -> void {
|
||||
gtkMenu = gtk_menu_new();
|
||||
widget = gtk_image_menu_item_new_with_mnemonic("");
|
||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(widget), gtkMenu);
|
||||
setImage(state().image);
|
||||
setText(state().text);
|
||||
|
||||
for(auto& action : state().actions) append(*action);
|
||||
@@ -27,16 +28,16 @@ auto pMenu::append(sAction action) -> void {
|
||||
auto pMenu::remove(sAction action) -> void {
|
||||
}
|
||||
|
||||
auto pMenu::setFont(const string& font) -> void {
|
||||
auto pMenu::setFont(const Font& font) -> void {
|
||||
pAction::setFont(font);
|
||||
for(auto& action : state().actions) {
|
||||
if(action->self()) action->self()->setFont(action->font(true));
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenu::setIcon(const image& icon) -> void {
|
||||
if(icon) {
|
||||
GtkImage* gtkImage = CreateImage(icon, true);
|
||||
auto pMenu::setImage(const Image& image) -> void {
|
||||
if(image) {
|
||||
GtkImage* gtkImage = CreateImage(image, true);
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), (GtkWidget*)gtkImage);
|
||||
} else {
|
||||
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(widget), nullptr);
|
||||
|
@@ -7,8 +7,8 @@ struct pMenu : pAction {
|
||||
|
||||
auto append(sAction action) -> void;
|
||||
auto remove(sAction action) -> void;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
GtkWidget* gtkMenu = nullptr;
|
||||
|
@@ -2,67 +2,54 @@
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pFont::serif(unsigned size, string style) -> string {
|
||||
if(size == 0) size = 8;
|
||||
if(style == "") style = "Normal";
|
||||
return {"Serif, ", size, ", ", style};
|
||||
}
|
||||
|
||||
auto pFont::sans(unsigned size, string style) -> string {
|
||||
if(size == 0) size = 8;
|
||||
if(style == "") style = "Normal";
|
||||
return {"Sans, ", size, ", ", style};
|
||||
}
|
||||
|
||||
auto pFont::monospace(unsigned size, string style) -> string {
|
||||
if(size == 0) size = 8;
|
||||
return {"Liberation Mono, ", size, ", ", style};
|
||||
}
|
||||
|
||||
auto pFont::size(string font, string text) -> Size {
|
||||
auto pFont::size(const Font& font, const string& text) -> Size {
|
||||
PangoFontDescription* description = create(font);
|
||||
Size size = pFont::size(description, text);
|
||||
free(description);
|
||||
return size;
|
||||
}
|
||||
|
||||
auto pFont::create(string description) -> PangoFontDescription* {
|
||||
lstring part = description.split(",", 2L).strip();
|
||||
auto pFont::size(PangoFontDescription* font, const string& text) -> Size {
|
||||
PangoContext* context = gdk_pango_context_get_for_screen(gdk_screen_get_default());
|
||||
PangoLayout* layout = pango_layout_new(context);
|
||||
pango_layout_set_font_description(layout, font);
|
||||
pango_layout_set_text(layout, text, -1);
|
||||
signed width = 0, height = 0;
|
||||
pango_layout_get_pixel_size(layout, &width, &height);
|
||||
g_object_unref((gpointer)layout);
|
||||
return {width, height};
|
||||
}
|
||||
|
||||
string family = "Sans";
|
||||
unsigned size = 8u;
|
||||
bool bold = false;
|
||||
bool italic = false;
|
||||
auto pFont::family(const string& family) -> string {
|
||||
#if defined(DISPLAY_WINDOWS)
|
||||
if(family == Font::Sans ) return "Tahoma";
|
||||
if(family == Font::Serif) return "Georgia";
|
||||
if(family == Font::Mono ) return "Lucida Console";
|
||||
return family ? family : "Tahoma";
|
||||
#elif defined(DISPLAY_XORG)
|
||||
if(family == Font::Sans ) return "Sans";
|
||||
if(family == Font::Serif) return "Serif";
|
||||
if(family == Font::Mono ) return "Liberation Mono";
|
||||
return family ? family : "Sans";
|
||||
#else
|
||||
return family;
|
||||
#endif
|
||||
}
|
||||
|
||||
if(part[0] != "") family = part[0];
|
||||
if(part.size() >= 2) size = decimal(part[1]);
|
||||
if(part.size() >= 3) bold = (bool)part[2].find("Bold");
|
||||
if(part.size() >= 3) italic = (bool)part[2].find("Italic");
|
||||
|
||||
PangoFontDescription* font = pango_font_description_new();
|
||||
pango_font_description_set_family(font, family);
|
||||
pango_font_description_set_size(font, size * PANGO_SCALE);
|
||||
pango_font_description_set_weight(font, !bold ? PANGO_WEIGHT_NORMAL : PANGO_WEIGHT_BOLD);
|
||||
pango_font_description_set_style(font, !italic ? PANGO_STYLE_NORMAL : PANGO_STYLE_OBLIQUE);
|
||||
return font;
|
||||
auto pFont::create(const Font& font) -> PangoFontDescription* {
|
||||
auto p = pango_font_description_new();
|
||||
pango_font_description_set_family(p, family(font.family()));
|
||||
pango_font_description_set_size(p, (font.size() ? font.size() : 8) * PANGO_SCALE);
|
||||
pango_font_description_set_weight(p, font.bold() ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
|
||||
pango_font_description_set_style(p, font.italic() ? PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL);
|
||||
return p;
|
||||
}
|
||||
|
||||
auto pFont::free(PangoFontDescription* font) -> void {
|
||||
pango_font_description_free(font);
|
||||
}
|
||||
|
||||
auto pFont::size(PangoFontDescription* font, string text) -> Size {
|
||||
PangoContext* context = gdk_pango_context_get_for_screen(gdk_screen_get_default());
|
||||
PangoLayout* layout = pango_layout_new(context);
|
||||
pango_layout_set_font_description(layout, font);
|
||||
pango_layout_set_text(layout, text, -1);
|
||||
int width = 0, height = 0;
|
||||
pango_layout_get_pixel_size(layout, &width, &height);
|
||||
g_object_unref((gpointer)layout);
|
||||
return {width, height};
|
||||
}
|
||||
|
||||
auto pFont::setFont(GtkWidget* widget, string font) -> void {
|
||||
auto pFont::setFont(GtkWidget* widget, const Font& font) -> void {
|
||||
auto gtkFont = pFont::create(font);
|
||||
pFont::setFont(widget, (gpointer)gtkFont);
|
||||
pFont::free(gtkFont);
|
||||
|
@@ -3,15 +3,12 @@
|
||||
namespace hiro {
|
||||
|
||||
struct pFont {
|
||||
static auto serif(unsigned size, string style) -> string;
|
||||
static auto sans(unsigned size, string style) -> string;
|
||||
static auto monospace(unsigned size, string style) -> string;
|
||||
static auto size(string font, string text) -> Size;
|
||||
|
||||
static auto create(string description) -> PangoFontDescription*;
|
||||
static auto size(const Font& font, const string& text) -> Size;
|
||||
static auto size(PangoFontDescription* font, const string& text) -> Size;
|
||||
static auto family(const string& family) -> string;
|
||||
static auto create(const Font& font) -> PangoFontDescription*;
|
||||
static auto free(PangoFontDescription* font) -> void;
|
||||
static auto size(PangoFontDescription* font, string text) -> Size;
|
||||
static auto setFont(GtkWidget* widget, string font) -> void;
|
||||
static auto setFont(GtkWidget* widget, const Font& font) -> void;
|
||||
static auto setFont(GtkWidget* widget, gpointer font) -> void;
|
||||
};
|
||||
|
||||
|
@@ -1,13 +0,0 @@
|
||||
#if defined(Hiro_Hotkey)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pHotkey::construct() -> void {
|
||||
}
|
||||
|
||||
auto pHotkey::destruct() -> void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,11 +0,0 @@
|
||||
#if defined(Hiro_Hotkey)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pHotkey : pObject {
|
||||
Declare(Hotkey, Object)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -13,7 +13,7 @@ auto pLayout::destruct() -> void {
|
||||
auto pLayout::setEnabled(bool enabled) -> void {
|
||||
}
|
||||
|
||||
auto pLayout::setFont(const string& font) -> void {
|
||||
auto pLayout::setFont(const Font& font) -> void {
|
||||
}
|
||||
|
||||
auto pLayout::setVisible(bool visible) -> void {
|
||||
|
@@ -6,7 +6,7 @@ struct pLayout : pSizable {
|
||||
Declare(Layout, Sizable)
|
||||
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
};
|
||||
|
||||
|
@@ -27,7 +27,7 @@ auto pMenuBar::setEnabled(bool enabled) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pMenuBar::setFont(const string& font) -> void {
|
||||
auto pMenuBar::setFont(const Font& font) -> void {
|
||||
if(auto parent = _parent()) {
|
||||
parent->_setMenuFont(font);
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ struct pMenuBar : pObject {
|
||||
auto append(sMenu menu) -> void;
|
||||
auto remove(sMenu menu) -> void;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
auto _parent() -> pWindow*;
|
||||
|
@@ -24,7 +24,7 @@ auto pObject::setEnabled(bool enabled) -> void {
|
||||
auto pObject::setFocused() -> void {
|
||||
}
|
||||
|
||||
auto pObject::setFont(const string& font) -> void {
|
||||
auto pObject::setFont(const Font& font) -> void {
|
||||
}
|
||||
|
||||
auto pObject::setVisible(bool visible) -> void {
|
||||
|
@@ -15,7 +15,7 @@ struct pObject {
|
||||
virtual auto reset() -> void;
|
||||
virtual auto setEnabled(bool enabled) -> void;
|
||||
virtual auto setFocused() -> void;
|
||||
virtual auto setFont(const string& font) -> void;
|
||||
virtual auto setFont(const Font& font) -> void;
|
||||
virtual auto setVisible(bool visible) -> void;
|
||||
|
||||
auto locked() const -> bool { return locks != 0; }
|
||||
|
@@ -12,7 +12,6 @@
|
||||
#include "object.cpp"
|
||||
#include "group.cpp"
|
||||
|
||||
#include "hotkey.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "window.cpp"
|
||||
#include "status-bar.cpp"
|
||||
|
@@ -23,7 +23,6 @@ namespace hiro {
|
||||
#include "object.hpp"
|
||||
#include "group.hpp"
|
||||
|
||||
#include "hotkey.hpp"
|
||||
#include "timer.hpp"
|
||||
#include "window.hpp"
|
||||
#include "status-bar.hpp"
|
||||
|
@@ -21,7 +21,7 @@ auto pPopupMenu::append(sAction action) -> void {
|
||||
auto pPopupMenu::remove(sAction action) -> void {
|
||||
}
|
||||
|
||||
auto pPopupMenu::setFont(const string& font) -> void {
|
||||
auto pPopupMenu::setFont(const Font& font) -> void {
|
||||
for(auto& action : state().actions) {
|
||||
if(action->self()) action->self()->setFont(action->font(true));
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ struct pPopupMenu : pObject {
|
||||
|
||||
auto append(sAction action) -> void;
|
||||
auto remove(sAction action) -> void;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setVisible(bool visible) -> void;
|
||||
|
||||
GtkWidget* gtkMenu = nullptr;
|
||||
|
@@ -14,7 +14,7 @@ auto pStatusBar::setEnabled(bool enabled) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pStatusBar::setFont(const string& font) -> void {
|
||||
auto pStatusBar::setFont(const Font& font) -> void {
|
||||
if(auto parent = _parent()) {
|
||||
parent->_setStatusFont(font);
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ struct pStatusBar : pObject {
|
||||
Declare(StatusBar, Object)
|
||||
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
|
@@ -20,6 +20,34 @@ static auto CreatePixbuf(image icon, bool scale = false) -> GdkPixbuf* {
|
||||
auto pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, icon.width(), icon.height());
|
||||
memory::copy(gdk_pixbuf_get_pixels(pixbuf), icon.data(), icon.size());
|
||||
|
||||
if(scale) {
|
||||
auto scaled = gdk_pixbuf_scale_simple(pixbuf, 15, 15, GDK_INTERP_BILINEAR);
|
||||
g_object_unref(pixbuf);
|
||||
pixbuf = scaled;
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static auto CreatePixbuf(const Image& image, bool scale = false) -> GdkPixbuf* {
|
||||
if(!image.state.data) return nullptr;
|
||||
|
||||
auto pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, image.width(), image.height());
|
||||
|
||||
//ARGB -> ABGR conversion
|
||||
const uint32_t* source = image.data();
|
||||
uint32_t* target = (uint32_t*)gdk_pixbuf_get_pixels(pixbuf);
|
||||
for(auto n : range(image.width() * image.height())) {
|
||||
uint32_t pixel = *source++;
|
||||
*target++ = (pixel & 0x00ff0000) >> 16 | (pixel & 0xff00ff00) | (pixel & 0x000000ff) << 16;
|
||||
}
|
||||
|
||||
if(scale) {
|
||||
auto scaled = gdk_pixbuf_scale_simple(pixbuf, 15, 15, GDK_INTERP_BILINEAR);
|
||||
g_object_unref(pixbuf);
|
||||
pixbuf = scaled;
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
@@ -30,6 +58,13 @@ static auto CreateImage(const nall::image& image, bool scale = false) -> GtkImag
|
||||
return gtkImage;
|
||||
}
|
||||
|
||||
static auto CreateImage(const Image& image, bool scale = false) -> GtkImage* {
|
||||
auto pixbuf = CreatePixbuf(image, scale);
|
||||
auto gtkImage = (GtkImage*)gtk_image_new_from_pixbuf(pixbuf);
|
||||
g_object_unref(pixbuf);
|
||||
return gtkImage;
|
||||
}
|
||||
|
||||
static auto DropPaths(GtkSelectionData* data) -> lstring {
|
||||
gchar** uris = gtk_selection_data_get_uris(data);
|
||||
if(uris == nullptr) return {};
|
||||
|
@@ -9,7 +9,7 @@ auto pButton::construct() -> void {
|
||||
gtkButton = GTK_BUTTON(gtkWidget);
|
||||
|
||||
setBordered(state().bordered);
|
||||
setIcon(state().icon);
|
||||
setImage(state().image);
|
||||
setOrientation(state().orientation);
|
||||
setText(state().text);
|
||||
|
||||
@@ -26,13 +26,13 @@ auto pButton::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
|
||||
if(state().orientation == Orientation::Horizontal) {
|
||||
size.setWidth(size.width() + state().icon.width());
|
||||
size.setHeight(max(size.height(), state().icon.height()));
|
||||
size.setWidth(size.width() + state().image.width());
|
||||
size.setHeight(max(size.height(), state().image.height()));
|
||||
}
|
||||
|
||||
if(state().orientation == Orientation::Vertical) {
|
||||
size.setWidth(max(size.width(), state().icon.width()));
|
||||
size.setHeight(size.height() + state().icon.height());
|
||||
size.setWidth(max(size.width(), state().image.width()));
|
||||
size.setHeight(size.height() + state().image.height());
|
||||
}
|
||||
|
||||
return {size.width() + (state().text ? 24 : 12), size.height() + 12};
|
||||
@@ -42,9 +42,9 @@ auto pButton::setBordered(bool bordered) -> void {
|
||||
gtk_button_set_relief(gtkButton, bordered ? GTK_RELIEF_NORMAL : GTK_RELIEF_NONE);
|
||||
}
|
||||
|
||||
auto pButton::setIcon(const image& icon) -> void {
|
||||
if(icon) {
|
||||
auto gtkImage = CreateImage(icon);
|
||||
auto pButton::setImage(const Image& image) -> void {
|
||||
if(image) {
|
||||
auto gtkImage = CreateImage(image);
|
||||
gtk_button_set_image(gtkButton, (GtkWidget*)gtkImage);
|
||||
} else {
|
||||
gtk_button_set_image(gtkButton, nullptr);
|
||||
|
@@ -7,7 +7,7 @@ struct pButton : pWidget {
|
||||
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setBordered(bool bordered) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setOrientation(Orientation orientation) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
|
@@ -73,16 +73,11 @@ auto pCanvas::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pCanvas::minimumSize() const -> Size {
|
||||
return {max(0, state().size.width()), max(0, state().size.height())};
|
||||
if(auto& image = state().image) return image.size();
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
auto pCanvas::setColor(Color color) -> void {
|
||||
mode = Mode::Color;
|
||||
update();
|
||||
}
|
||||
|
||||
auto pCanvas::setData(Size size) -> void {
|
||||
mode = Mode::Data;
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -98,13 +93,11 @@ auto pCanvas::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry(geometry);
|
||||
}
|
||||
|
||||
auto pCanvas::setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) -> void {
|
||||
mode = Mode::Gradient;
|
||||
auto pCanvas::setGradient(Gradient gradient) -> void {
|
||||
update();
|
||||
}
|
||||
|
||||
auto pCanvas::setIcon(const image& icon) -> void {
|
||||
mode = Mode::Icon;
|
||||
auto pCanvas::setImage(const Image& image) -> void {
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -146,14 +139,13 @@ auto pCanvas::_rasterize() -> void {
|
||||
signed width = 0;
|
||||
signed height = 0;
|
||||
|
||||
if(mode == Mode::Color || mode == Mode::Gradient) {
|
||||
if(auto& image = state().image) {
|
||||
width = image.width();
|
||||
height = image.height();
|
||||
} else {
|
||||
width = pSizable::state().geometry.width();
|
||||
height = pSizable::state().geometry.height();
|
||||
} else {
|
||||
width = state().size.width();
|
||||
height = state().size.height();
|
||||
}
|
||||
|
||||
if(width <= 0 || height <= 0) return;
|
||||
|
||||
if(width != surfaceWidth || height != surfaceHeight) _release();
|
||||
@@ -161,33 +153,21 @@ auto pCanvas::_rasterize() -> void {
|
||||
surfaceHeight = height;
|
||||
|
||||
if(!surface) surface = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, width, height);
|
||||
uint32_t* buffer = (uint32_t*)gdk_pixbuf_get_pixels(surface);
|
||||
auto buffer = (uint32_t*)gdk_pixbuf_get_pixels(surface);
|
||||
|
||||
if(mode == Mode::Color) {
|
||||
if(auto& image = state().image) {
|
||||
memory::copy(buffer, state().image.data(), width * height * sizeof(uint32_t));
|
||||
} else if(auto& gradient = state().gradient) {
|
||||
auto& colors = gradient.state.colors;
|
||||
nall::image fill;
|
||||
fill.allocate(width, height);
|
||||
fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value());
|
||||
memory::copy(buffer, fill.data(), fill.size());
|
||||
} else {
|
||||
uint32_t color = state().color.value();
|
||||
for(auto n : range(width * height)) buffer[n] = color;
|
||||
}
|
||||
|
||||
if(mode == Mode::Gradient) {
|
||||
image fill;
|
||||
fill.allocate(width, height);
|
||||
fill.gradient(
|
||||
state().gradient[0].value(), state().gradient[1].value(), state().gradient[2].value(), state().gradient[3].value()
|
||||
);
|
||||
memory::copy(buffer, fill.data(), fill.size());
|
||||
}
|
||||
|
||||
if(mode == Mode::Icon) {
|
||||
auto icon = state().icon;
|
||||
icon.scale(width, height);
|
||||
icon.transform();
|
||||
memory::copy(buffer, icon.data(), icon.size());
|
||||
}
|
||||
|
||||
if(mode == Mode::Data) {
|
||||
memory::copy(buffer, state().data.data(), state().data.size() * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
//ARGB -> ABGR conversion
|
||||
for(auto n : range(width * height)) {
|
||||
uint32_t color = *buffer;
|
||||
|
@@ -7,15 +7,12 @@ struct pCanvas : pWidget {
|
||||
|
||||
auto minimumSize() const -> Size;
|
||||
auto setColor(Color color) -> void;
|
||||
auto setData(Size size) -> void;
|
||||
auto setDroppable(bool droppable) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setGradient(Color topLeft, Color topRight, Color bottomLeft, Color bottomRight) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setGradient(Gradient gradient) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto update() -> void;
|
||||
|
||||
enum class Mode : unsigned { Color, Data, Gradient, Icon };
|
||||
|
||||
auto _onExpose(GdkEventExpose* event) -> void;
|
||||
auto _rasterize() -> void;
|
||||
auto _redraw() -> void;
|
||||
@@ -24,7 +21,6 @@ struct pCanvas : pWidget {
|
||||
GdkPixbuf* surface = nullptr;
|
||||
unsigned surfaceWidth = 0;
|
||||
unsigned surfaceHeight = 0;
|
||||
Mode mode = Mode::Color;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ auto pCheckButton::construct() -> void {
|
||||
|
||||
setBordered(state().bordered);
|
||||
setChecked(state().checked);
|
||||
setIcon(state().icon);
|
||||
setImage(state().image);
|
||||
setOrientation(state().orientation);
|
||||
setText(state().text);
|
||||
|
||||
@@ -29,13 +29,13 @@ auto pCheckButton::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
|
||||
if(state().orientation == Orientation::Horizontal) {
|
||||
size.setWidth(size.width() + state().icon.width());
|
||||
size.setHeight(max(size.height(), state().icon.height()));
|
||||
size.setWidth(size.width() + state().image.width());
|
||||
size.setHeight(max(size.height(), state().image.height()));
|
||||
}
|
||||
|
||||
if(state().orientation == Orientation::Vertical) {
|
||||
size.setWidth(max(size.width(), state().icon.width()));
|
||||
size.setHeight(size.height() + state().icon.height());
|
||||
size.setWidth(max(size.width(), state().image.width()));
|
||||
size.setHeight(size.height() + state().image.height());
|
||||
}
|
||||
|
||||
return {size.width() + 24, size.height() + 12};
|
||||
@@ -51,9 +51,9 @@ auto pCheckButton::setChecked(bool checked) -> void {
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto pCheckButton::setIcon(const image& icon) -> void {
|
||||
if(icon) {
|
||||
GtkImage* gtkImage = CreateImage(icon);
|
||||
auto pCheckButton::setImage(const Image& image) -> void {
|
||||
if(image) {
|
||||
GtkImage* gtkImage = CreateImage(image);
|
||||
gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage);
|
||||
} else {
|
||||
gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr);
|
||||
|
@@ -8,7 +8,7 @@ struct pCheckButton : pWidget {
|
||||
auto minimumSize() const -> Size override;
|
||||
auto setBordered(bool bordered) -> void;
|
||||
auto setChecked(bool checked) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setOrientation(Orientation orientation) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
};
|
||||
|
@@ -8,11 +8,10 @@ auto pComboButtonItem::construct() -> void {
|
||||
auto pComboButtonItem::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pComboButtonItem::setIcon(image icon) -> void {
|
||||
auto pComboButtonItem::setImage(const Image& image) -> void {
|
||||
if(auto parent = _parent()) {
|
||||
auto size = pFont::size(self().font(true), " ").height();
|
||||
if(icon) icon.scale(size, size);
|
||||
auto pixbuf = CreatePixbuf(icon);
|
||||
auto pixbuf = CreatePixbuf(image, true);
|
||||
gtk_list_store_set(parent->gtkListStore, >kIter, 0, pixbuf, -1);
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ namespace hiro {
|
||||
struct pComboButtonItem : pObject {
|
||||
Declare(ComboButtonItem, Object)
|
||||
|
||||
auto setIcon(image icon) -> void;
|
||||
auto setImage(const Image& icon) -> void;
|
||||
auto setSelected() -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
|
@@ -32,7 +32,7 @@ auto pComboButton::append(sComboButtonItem item) -> void {
|
||||
lock();
|
||||
if(auto self = item->self()) {
|
||||
gtk_list_store_append(gtkListStore, &self->gtkIter);
|
||||
self->setIcon(item->state.icon);
|
||||
self->setImage(item->state.image);
|
||||
if(item->state.selected) self->setSelected();
|
||||
self->setText(item->state.text);
|
||||
}
|
||||
@@ -41,11 +41,11 @@ auto pComboButton::append(sComboButtonItem item) -> void {
|
||||
}
|
||||
|
||||
auto pComboButton::minimumSize() const -> Size {
|
||||
string font = self().font(true);
|
||||
auto font = self().font(true);
|
||||
signed maximumWidth = 0;
|
||||
for(auto& item : state().items) {
|
||||
maximumWidth = max(maximumWidth,
|
||||
(item->state.icon ? pFont::size(font, " ").height() + 2 : 0)
|
||||
(item->state.image ? pFont::size(font, " ").height() + 2 : 0)
|
||||
+ pFont::size(font, item->state.text).width()
|
||||
);
|
||||
}
|
||||
@@ -69,7 +69,7 @@ auto pComboButton::reset() -> void {
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto pComboButton::setFont(const string& font) -> void {
|
||||
auto pComboButton::setFont(const Font& font) -> void {
|
||||
pWidget::setFont(font);
|
||||
auto fontDescription = pFont::create(font);
|
||||
g_object_set(G_OBJECT(gtkCellText), "font-desc", fontDescription, nullptr);
|
||||
|
@@ -9,7 +9,7 @@ struct pComboButton : pWidget {
|
||||
auto minimumSize() const -> Size override;
|
||||
auto remove(sComboButtonItem item) -> void;
|
||||
auto reset() -> void;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
|
||||
auto _updateSelected() -> void;
|
||||
|
||||
|
@@ -33,7 +33,7 @@ auto pFrame::setEnabled(bool enabled) -> void {
|
||||
pWidget::setEnabled(enabled);
|
||||
}
|
||||
|
||||
auto pFrame::setFont(const string& font) -> void {
|
||||
auto pFrame::setFont(const Font& font) -> void {
|
||||
if(auto layout = _layout()) layout->setFont(layout->self().font(true));
|
||||
pFont::setFont(gtkLabel, font);
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ struct pFrame : pWidget {
|
||||
auto container(mWidget& widget) -> GtkWidget* override;
|
||||
auto remove(shared_pointer<mLayout> layout) -> void;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
@@ -8,9 +8,9 @@ auto pIconViewItem::construct() -> void {
|
||||
auto pIconViewItem::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pIconViewItem::setIcon(const image& icon) -> void {
|
||||
auto pIconViewItem::setImage(const Image& image) -> void {
|
||||
if(auto parent = _parent()) {
|
||||
parent->setItemIcon(self().offset(), icon);
|
||||
parent->setItemImage(self().offset(), image);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,7 @@ namespace hiro {
|
||||
struct pIconViewItem : pObject {
|
||||
Declare(IconViewItem, Object)
|
||||
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setSelected(bool selected) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
|
@@ -39,9 +39,9 @@ auto pIconView::construct() -> void {
|
||||
gtk_widget_show(subWidget);
|
||||
|
||||
setBackgroundColor(state().backgroundColor);
|
||||
setBatchable(state().batchable);
|
||||
setFlow(state().flow);
|
||||
setForegroundColor(state().foregroundColor);
|
||||
setMultiSelect(state().multiSelect);
|
||||
setOrientation(state().orientation);
|
||||
for(auto position : range(self().items())) {
|
||||
auto& item = state().items[position];
|
||||
@@ -65,7 +65,7 @@ auto pIconView::destruct() -> void {
|
||||
auto pIconView::append(sIconViewItem item) -> void {
|
||||
GtkTreeIter iter;
|
||||
gtk_list_store_append(store, &iter);
|
||||
setItemIcon(item->offset(), item->state.icon);
|
||||
setItemImage(item->offset(), item->state.image);
|
||||
setItemSelected(item->offset(), item->state.selected);
|
||||
setItemText(item->offset(), item->state.text);
|
||||
}
|
||||
@@ -92,6 +92,12 @@ auto pIconView::setBackgroundColor(Color color) -> void {
|
||||
gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
}
|
||||
|
||||
auto pIconView::setBatchable(bool batchable) -> void {
|
||||
gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(subWidget),
|
||||
batchable ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE
|
||||
);
|
||||
}
|
||||
|
||||
auto pIconView::setFlow(Orientation flow) -> void {
|
||||
//GTK+ does not support vertical flow ... the closest we can get is a horizontal flow with only one column
|
||||
if(flow == Orientation::Horizontal) {
|
||||
@@ -115,12 +121,12 @@ auto pIconView::setGeometry(Geometry geometry) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pIconView::setItemIcon(unsigned position, const image& icon) -> void {
|
||||
auto pIconView::setItemImage(unsigned position, const Image& image) -> void {
|
||||
if(position >= self().itemCount()) return;
|
||||
GtkTreeIter iter;
|
||||
if(gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, string{position})) {
|
||||
if(icon) {
|
||||
GdkPixbuf* pixbuf = CreatePixbuf(icon);
|
||||
if(image) {
|
||||
GdkPixbuf* pixbuf = CreatePixbuf(image);
|
||||
gtk_list_store_set(store, &iter, 0, pixbuf, -1);
|
||||
} else {
|
||||
gtk_list_store_set(store, &iter, 0, nullptr, -1);
|
||||
@@ -172,12 +178,6 @@ auto pIconView::setItemText(unsigned position, const string& text) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pIconView::setMultiSelect(bool multiSelect) -> void {
|
||||
gtk_icon_view_set_selection_mode(GTK_ICON_VIEW(subWidget),
|
||||
multiSelect ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE
|
||||
);
|
||||
}
|
||||
|
||||
auto pIconView::setOrientation(Orientation orientation) -> void {
|
||||
gtk_icon_view_set_item_orientation(GTK_ICON_VIEW(subWidget),
|
||||
orientation == Orientation::Horizontal ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL
|
||||
|
@@ -9,16 +9,16 @@ struct pIconView : pWidget {
|
||||
auto remove(sIconViewItem item) -> void;
|
||||
auto reset() -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setBatchable(bool batchable) -> void;
|
||||
auto setFlow(Orientation flow) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void;
|
||||
auto setItemIcon(unsigned position, const image& icon) -> void;
|
||||
auto setItemImage(unsigned position, const Image& image) -> void;
|
||||
auto setItemSelected(unsigned position, bool selected) -> void;
|
||||
auto setItemSelected(const vector<signed>& selections) -> void;
|
||||
auto setItemSelectedAll() -> void;
|
||||
auto setItemSelectedNone() -> void;
|
||||
auto setItemText(unsigned position, const string& text) -> void;
|
||||
auto setMultiSelect(bool multiSelect) -> void;
|
||||
auto setOrientation(Orientation orientation) -> void;
|
||||
|
||||
auto _updateSelected() -> void;
|
||||
|
@@ -25,7 +25,7 @@ auto pListViewCell::setChecked(bool checked) -> void {
|
||||
auto pListViewCell::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListViewCell::setIcon(const image& icon) -> void {
|
||||
auto pListViewCell::setImage(const Image& image) -> void {
|
||||
_setState();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ auto pListViewCell::_setState() -> void {
|
||||
if(auto grandparent = _grandparent()) {
|
||||
grandparent->lock();
|
||||
gtk_list_store_set(grandparent->gtkListStore, &parent->gtkIter, 3 * self().offset() + 0, state().checked, -1);
|
||||
gtk_list_store_set(grandparent->gtkListStore, &parent->gtkIter, 3 * self().offset() + 1, CreatePixbuf(state().icon), -1);
|
||||
gtk_list_store_set(grandparent->gtkListStore, &parent->gtkIter, 3 * self().offset() + 1, CreatePixbuf(state().image), -1);
|
||||
gtk_list_store_set(grandparent->gtkListStore, &parent->gtkIter, 3 * self().offset() + 2, state().text.data(), -1);
|
||||
grandparent->unlock();
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ struct pListViewCell : pObject {
|
||||
auto setCheckable(bool checkable) -> void;
|
||||
auto setChecked(bool checked) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
auto _grandparent() -> maybe<pListView&>;
|
||||
|
@@ -75,15 +75,15 @@ auto pListViewColumn::setExpandable(bool expandable) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pListViewColumn::setFont(const string& font) -> void {
|
||||
auto pListViewColumn::setFont(const Font& font) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pListViewColumn::setIcon(const image& icon) -> void {
|
||||
if(icon) {
|
||||
gtk_image_set_from_pixbuf(GTK_IMAGE(gtkHeaderIcon), CreatePixbuf(icon));
|
||||
auto pListViewColumn::setImage(const Image& image) -> void {
|
||||
if(image) {
|
||||
gtk_image_set_from_pixbuf(GTK_IMAGE(gtkHeaderIcon), CreatePixbuf(image));
|
||||
} else {
|
||||
gtk_image_clear(GTK_IMAGE(gtkHeaderIcon));
|
||||
}
|
||||
|
@@ -10,10 +10,10 @@ struct pListViewColumn : pObject {
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setEditable(bool editable) -> void;
|
||||
auto setExpandable(bool expandable) -> void;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setHorizontalAlignment(double) -> void {}
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setResizable(bool resizable) -> void;
|
||||
auto setSortable(bool sortable) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
@@ -122,7 +122,7 @@ auto pListView::setFocused() -> void {
|
||||
gtk_widget_grab_focus(gtkWidgetChild);
|
||||
}
|
||||
|
||||
auto pListView::setFont(const string& font) -> void {
|
||||
auto pListView::setFont(const Font& font) -> void {
|
||||
if(auto& header = state().header) {
|
||||
if(auto self = header->self()) self->_setState();
|
||||
}
|
||||
@@ -149,11 +149,11 @@ auto pListView::_cellWidth(unsigned _row, unsigned _column) -> unsigned {
|
||||
if(cell->state.checkable) {
|
||||
width += 24;
|
||||
}
|
||||
if(auto& icon = cell->state.icon) {
|
||||
width += icon.width() + 2;
|
||||
if(auto& image = cell->state.image) {
|
||||
width += image.width() + 2;
|
||||
}
|
||||
if(auto& text = cell->state.text) {
|
||||
width += Font::size(cell->font(true), text).width();
|
||||
width += pFont::size(cell->font(true), text).width();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,11 +164,11 @@ auto pListView::_columnWidth(unsigned _column) -> unsigned {
|
||||
unsigned width = 8;
|
||||
if(auto& header = state().header) {
|
||||
if(auto column = header->column(_column)) {
|
||||
if(auto& icon = column->state.icon) {
|
||||
width += icon.width() + 2;
|
||||
if(auto& image = column->state.image) {
|
||||
width += image.width() + 2;
|
||||
}
|
||||
if(auto& text = column->state.text) {
|
||||
width += Font::size(column->font(true), text).width();
|
||||
width += pFont::size(column->font(true), text).width();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ struct pListView : pWidget {
|
||||
auto setBatchable(bool batchable) -> void;
|
||||
auto setBordered(bool bordered) -> void;
|
||||
auto setFocused() -> void override;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
|
||||
|
@@ -5,7 +5,7 @@ namespace hiro {
|
||||
static auto RadioButton_activate(GtkToggleButton*, pRadioButton* p) -> void {
|
||||
if(p->groupLocked()) return;
|
||||
bool wasChecked = p->state().checked;
|
||||
p->setChecked();
|
||||
p->self().setChecked();
|
||||
if(!wasChecked) p->self().doActivate();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ auto pRadioButton::construct() -> void {
|
||||
gtkWidget = gtk_toggle_button_new();
|
||||
|
||||
setBordered(state().bordered);
|
||||
setIcon(state().icon);
|
||||
setImage(state().image);
|
||||
setOrientation(state().orientation);
|
||||
setText(state().text);
|
||||
|
||||
@@ -30,13 +30,13 @@ auto pRadioButton::minimumSize() const -> Size {
|
||||
Size size = pFont::size(self().font(true), state().text);
|
||||
|
||||
if(state().orientation == Orientation::Horizontal) {
|
||||
size.setWidth(size.width() + state().icon.width());
|
||||
size.setHeight(max(size.height(), state().icon.height()));
|
||||
size.setWidth(size.width() + state().image.width());
|
||||
size.setHeight(max(size.height(), state().image.height()));
|
||||
}
|
||||
|
||||
if(state().orientation == Orientation::Vertical) {
|
||||
size.setWidth(max(size.width(), state().icon.width()));
|
||||
size.setHeight(size.height() + state().icon.height());
|
||||
size.setWidth(max(size.width(), state().image.width()));
|
||||
size.setHeight(size.height() + state().image.height());
|
||||
}
|
||||
|
||||
return {size.width() + 24, size.height() + 12};
|
||||
@@ -47,14 +47,12 @@ auto pRadioButton::setBordered(bool bordered) -> void {
|
||||
}
|
||||
|
||||
auto pRadioButton::setChecked() -> void {
|
||||
if(!self().group()) return;
|
||||
for(auto& weak : self().group()->state.objects) {
|
||||
if(auto object = weak.acquire()) {
|
||||
if(auto radioButton = dynamic_cast<mRadioButton*>(object.data())) {
|
||||
if(auto self = radioButton->self()) {
|
||||
self->lock();
|
||||
bool checked = self == this;
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->gtkWidget), radioButton->state.checked = checked);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->gtkWidget), radioButton->state.checked);
|
||||
self->unlock();
|
||||
}
|
||||
}
|
||||
@@ -63,13 +61,14 @@ auto pRadioButton::setChecked() -> void {
|
||||
}
|
||||
|
||||
auto pRadioButton::setGroup(sGroup group) -> void {
|
||||
if(!group) return;
|
||||
bool first = true;
|
||||
for(auto& weak : group->state.objects) {
|
||||
if(auto object = weak.acquire()) {
|
||||
if(auto radioButton = dynamic_cast<mRadioButton*>(object.data())) {
|
||||
if(auto self = radioButton->self()) {
|
||||
self->lock();
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->gtkWidget), radioButton->checked());
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->gtkWidget), radioButton->state.checked = first);
|
||||
first = false;
|
||||
self->unlock();
|
||||
}
|
||||
}
|
||||
@@ -77,9 +76,9 @@ auto pRadioButton::setGroup(sGroup group) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pRadioButton::setIcon(const image& icon) -> void {
|
||||
if(icon) {
|
||||
GtkImage* gtkImage = CreateImage(icon);
|
||||
auto pRadioButton::setImage(const Image& image) -> void {
|
||||
if(image) {
|
||||
GtkImage* gtkImage = CreateImage(image);
|
||||
gtk_button_set_image(GTK_BUTTON(gtkWidget), (GtkWidget*)gtkImage);
|
||||
} else {
|
||||
gtk_button_set_image(GTK_BUTTON(gtkWidget), nullptr);
|
||||
|
@@ -9,7 +9,7 @@ struct pRadioButton : pWidget {
|
||||
auto setBordered(bool bordered) -> void;
|
||||
auto setChecked() -> void;
|
||||
auto setGroup(sGroup group) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setOrientation(Orientation orientation) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
|
@@ -5,7 +5,7 @@ namespace hiro {
|
||||
static auto RadioLabel_activate(GtkToggleButton*, pRadioLabel* p) -> void {
|
||||
if(p->groupLocked()) return;
|
||||
bool wasChecked = p->state().checked;
|
||||
p->setChecked();
|
||||
p->self().setChecked();
|
||||
if(!wasChecked) p->self().doActivate();
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ auto pRadioLabel::setChecked() -> void {
|
||||
}
|
||||
|
||||
auto pRadioLabel::setGroup(sGroup group) -> void {
|
||||
if(!group) return;
|
||||
|
||||
maybe<GtkRadioButton*> gtkRadioButton;
|
||||
for(auto& weak : group->state.objects) {
|
||||
if(auto object = weak.acquire()) {
|
||||
@@ -46,9 +44,13 @@ auto pRadioLabel::setGroup(sGroup group) -> void {
|
||||
if(auto self = radioLabel->self()) {
|
||||
self->lock();
|
||||
gtk_radio_button_set_group(self->gtkRadioButton, nullptr);
|
||||
if(!gtkRadioButton) gtkRadioButton = self->gtkRadioButton;
|
||||
else gtk_radio_button_set_group(self->gtkRadioButton, gtk_radio_button_get_group(*gtkRadioButton));
|
||||
gtk_toggle_button_set_active(self->gtkToggleButton, radioLabel->checked());
|
||||
if(!gtkRadioButton) {
|
||||
gtkRadioButton = self->gtkRadioButton;
|
||||
gtk_toggle_button_set_active(self->gtkToggleButton, radioLabel->state.checked = true);
|
||||
} else {
|
||||
gtk_radio_button_set_group(self->gtkRadioButton, gtk_radio_button_get_group(*gtkRadioButton));
|
||||
gtk_toggle_button_set_active(self->gtkToggleButton, radioLabel->state.checked = false);
|
||||
}
|
||||
self->unlock();
|
||||
}
|
||||
}
|
||||
|
@@ -7,11 +7,11 @@ static auto SourceEdit_change(GtkTextBuffer*, pSourceEdit* p) -> void {
|
||||
}
|
||||
|
||||
static auto SourceEdit_move(GObject*, GParamSpec*, pSourceEdit* p) -> void {
|
||||
signed position = 0;
|
||||
g_object_get(G_OBJECT(p->gtkSourceBuffer), "cursor-position", &position, nullptr);
|
||||
signed offset = 0;
|
||||
g_object_get(G_OBJECT(p->gtkSourceBuffer), "cursor-position", &offset, nullptr);
|
||||
|
||||
if(p->state().position != position) {
|
||||
p->state().position = position;
|
||||
if(p->state().cursor.offset() != offset) {
|
||||
p->state().cursor.setOffset(offset);
|
||||
if(!p->locked()) p->self().doMove();
|
||||
}
|
||||
}
|
||||
@@ -68,10 +68,25 @@ auto pSourceEdit::destruct() -> void {
|
||||
gtk_widget_destroy(gtkWidget);
|
||||
}
|
||||
|
||||
auto pSourceEdit::setCursor(Cursor cursor) -> void {
|
||||
lock();
|
||||
GtkTextIter offset, length;
|
||||
gtk_text_buffer_get_end_iter(gtkTextBuffer, &offset);
|
||||
gtk_text_buffer_get_end_iter(gtkTextBuffer, &length);
|
||||
signed end = gtk_text_iter_get_offset(&offset);
|
||||
gtk_text_iter_set_offset(&offset, max(0, min(end, cursor.offset())));
|
||||
gtk_text_iter_set_offset(&length, max(0, min(end, cursor.offset() + cursor.length())));
|
||||
gtk_text_buffer_select_range(gtkTextBuffer, &offset, &length);
|
||||
auto mark = gtk_text_buffer_get_mark(gtkTextBuffer, "insert");
|
||||
gtk_text_view_scroll_mark_onscreen(gtkTextView, mark);
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto pSourceEdit::setFocused() -> void {
|
||||
gtk_widget_grab_focus(gtkWidgetSourceView);
|
||||
}
|
||||
|
||||
/*
|
||||
auto pSourceEdit::setPosition(signed position) -> void {
|
||||
lock();
|
||||
GtkTextIter iter;
|
||||
@@ -105,6 +120,7 @@ auto pSourceEdit::setSelected(Position selected) -> void {
|
||||
gtk_text_buffer_select_range(gtkTextBuffer, &startIter, &endIter);
|
||||
unlock();
|
||||
}
|
||||
*/
|
||||
|
||||
auto pSourceEdit::setText(const string& text) -> void {
|
||||
lock();
|
||||
|
@@ -5,9 +5,8 @@ namespace hiro {
|
||||
struct pSourceEdit : pWidget {
|
||||
Declare(SourceEdit, Widget)
|
||||
|
||||
auto setCursor(Cursor cursor) -> void;
|
||||
auto setFocused() -> void override;
|
||||
auto setPosition(signed position) -> void;
|
||||
auto setSelected(Position selected) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
auto text() const -> string;
|
||||
|
||||
|
@@ -22,9 +22,9 @@ auto pTabFrameItem::setClosable(bool closable) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pTabFrameItem::setIcon(const image& icon) -> void {
|
||||
auto pTabFrameItem::setImage(const Image& image) -> void {
|
||||
if(auto parent = _parent()) {
|
||||
parent->setItemIcon(self().offset(), icon);
|
||||
parent->setItemImage(self().offset(), image);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@ struct pTabFrameItem : pObject {
|
||||
auto append(sLayout layout) -> void;
|
||||
auto remove(sLayout layout) -> void;
|
||||
auto setClosable(bool closable) -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setMovable(bool movable) -> void;
|
||||
auto setSelected() -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
@@ -49,7 +49,7 @@ auto pTabFrame::construct() -> void {
|
||||
|
||||
tabs.reset(); //todo: memory leak, need to release each tab
|
||||
for(auto& item : state().items) append(item);
|
||||
setEdge(state().edge);
|
||||
setNavigation(state().navigation);
|
||||
|
||||
g_signal_connect(G_OBJECT(gtkWidget), "page-reordered", G_CALLBACK(TabFrame_move), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(gtkWidget), "switch-page", G_CALLBACK(TabFrame_change), (gpointer)this);
|
||||
@@ -72,7 +72,7 @@ auto pTabFrame::append(sTabFrameItem item) -> void {
|
||||
tab.close = gtk_button_new_with_label("\u00d7"); //Unicode multiplication sign (looks better than 'X')
|
||||
gtk_button_set_focus_on_click(GTK_BUTTON(tab.close), false);
|
||||
gtk_button_set_relief(GTK_BUTTON(tab.close), GTK_RELIEF_NONE);
|
||||
pFont::setFont(tab.close, Font::sans(9, "Bold"));
|
||||
pFont::setFont(tab.close, Font("sans", 9).setBold());
|
||||
auto color = CreateColor({255, 0, 0});
|
||||
gtk_widget_modify_fg(gtk_bin_get_child(GTK_BIN(tab.close)), GTK_STATE_PRELIGHT, &color);
|
||||
tabs.append(tab);
|
||||
@@ -140,18 +140,6 @@ auto pTabFrame::remove(sTabFrameItem item) -> void {
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto pTabFrame::setEdge(Edge edge) -> void {
|
||||
GtkPositionType type;
|
||||
switch(edge) { default:
|
||||
case Edge::Top: type = GTK_POS_TOP; break;
|
||||
case Edge::Bottom: type = GTK_POS_BOTTOM; break;
|
||||
case Edge::Left: type = GTK_POS_LEFT; break;
|
||||
case Edge::Right: type = GTK_POS_RIGHT; break;
|
||||
}
|
||||
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkWidget), type);
|
||||
setGeometry(self().geometry());
|
||||
}
|
||||
|
||||
auto pTabFrame::setEnabled(bool enabled) -> void {
|
||||
for(auto& item : state().items) {
|
||||
if(auto layout = item->state.layout) {
|
||||
@@ -161,7 +149,7 @@ auto pTabFrame::setEnabled(bool enabled) -> void {
|
||||
pWidget::setEnabled(enabled);
|
||||
}
|
||||
|
||||
auto pTabFrame::setFont(const string& font) -> void {
|
||||
auto pTabFrame::setFont(const Font& font) -> void {
|
||||
for(auto n : range(tabs.size())) {
|
||||
pFont::setFont(tabs[n].title, font);
|
||||
if(auto layout = state().items[n]->state.layout) {
|
||||
@@ -174,7 +162,7 @@ auto pTabFrame::setGeometry(Geometry geometry) -> void {
|
||||
pWidget::setGeometry(geometry);
|
||||
|
||||
geometry.setPosition(0, 0);
|
||||
if(state().edge == Edge::Top || state().edge == Edge::Bottom) {
|
||||
if(state().navigation == Navigation::Top || state().navigation == Navigation::Bottom) {
|
||||
geometry.setWidth(geometry.width() - 6);
|
||||
geometry.setHeight(geometry.height() - (15 + _tabHeight()));
|
||||
} else {
|
||||
@@ -190,7 +178,7 @@ auto pTabFrame::setItemClosable(unsigned position, bool closable) -> void {
|
||||
_synchronizeTab(position);
|
||||
}
|
||||
|
||||
auto pTabFrame::setItemIcon(unsigned position, const image& icon) -> void {
|
||||
auto pTabFrame::setItemImage(unsigned position, const Image& image) -> void {
|
||||
_synchronizeTab(position);
|
||||
}
|
||||
|
||||
@@ -214,6 +202,18 @@ auto pTabFrame::setItemText(unsigned position, const string& text) -> void {
|
||||
_synchronizeTab(position);
|
||||
}
|
||||
|
||||
auto pTabFrame::setNavigation(Navigation navigation) -> void {
|
||||
GtkPositionType type;
|
||||
switch(navigation) { default:
|
||||
case Navigation::Top: type = GTK_POS_TOP; break;
|
||||
case Navigation::Bottom: type = GTK_POS_BOTTOM; break;
|
||||
case Navigation::Left: type = GTK_POS_LEFT; break;
|
||||
case Navigation::Right: type = GTK_POS_RIGHT; break;
|
||||
}
|
||||
gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkWidget), type);
|
||||
setGeometry(self().geometry());
|
||||
}
|
||||
|
||||
auto pTabFrame::setVisible(bool visible) -> void {
|
||||
for(auto& item : state().items) {
|
||||
if(auto layout = item->state.layout) {
|
||||
@@ -239,16 +239,15 @@ auto pTabFrame::_synchronizeTab(unsigned position) -> void {
|
||||
auto& item = state().items[position];
|
||||
auto& tab = tabs[position];
|
||||
gtk_widget_set_visible(tab.close, item->closable());
|
||||
if(auto copy = item->state.icon) {
|
||||
if(auto& image = item->state.image) {
|
||||
unsigned size = pFont::size(self().font(true), " ").height();
|
||||
copy.scale(size, size);
|
||||
auto pixbuf = CreatePixbuf(copy);
|
||||
auto pixbuf = CreatePixbuf(image, true);
|
||||
gtk_image_set_from_pixbuf(GTK_IMAGE(tab.image), pixbuf);
|
||||
} else {
|
||||
gtk_image_clear(GTK_IMAGE(tab.image));
|
||||
}
|
||||
string text = {
|
||||
item->state.icon && item->state.text ? " " : "",
|
||||
item->state.image && item->state.text ? " " : "",
|
||||
item->state.text,
|
||||
item->state.text && item->state.closable ? " " : ""
|
||||
};
|
||||
|
@@ -8,16 +8,16 @@ struct pTabFrame : pWidget {
|
||||
auto append(sTabFrameItem item) -> void;
|
||||
auto container(mWidget& widget) -> GtkWidget* override;
|
||||
auto remove(sTabFrameItem item) -> void;
|
||||
auto setEdge(Edge edge) -> void;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setItemClosable(unsigned position, bool closable) -> void;
|
||||
auto setItemIcon(unsigned position, const image& icon) -> void;
|
||||
auto setItemImage(unsigned position, const Image& image) -> void;
|
||||
auto setItemLayout(unsigned position, sLayout layout) -> void;
|
||||
auto setItemMovable(unsigned position, bool movable) -> void;
|
||||
auto setItemSelected(unsigned position) -> void;
|
||||
auto setItemText(unsigned position, const string& text) -> void;
|
||||
auto setNavigation(Navigation navigation) -> void;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
auto _append(shared_pointer<mTabFrameItem> item) -> void;
|
||||
|
@@ -7,11 +7,11 @@ static auto TextEdit_change(GtkTextBuffer* textBuffer, pTextEdit* p) -> void {
|
||||
}
|
||||
|
||||
static auto TextEdit_move(GObject* object, GParamSpec* spec, pTextEdit* p) -> void {
|
||||
int position = 0;
|
||||
g_object_get(p->textBuffer, "cursor-position", &position, nullptr);
|
||||
signed offset = 0;
|
||||
g_object_get(p->textBuffer, "cursor-position", &offset, nullptr);
|
||||
|
||||
if(p->state().cursorPosition != position) {
|
||||
p->state().cursorPosition = position;
|
||||
if(p->state().cursor.offset() != offset) {
|
||||
p->state().cursor.setOffset(offset);
|
||||
if(!p->locked()) p->self().doMove();
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ auto pTextEdit::construct() -> void {
|
||||
setForegroundColor(state().foregroundColor);
|
||||
setText(state().text);
|
||||
setWordWrap(state().wordWrap);
|
||||
setCursor(state().cursor);
|
||||
|
||||
g_signal_connect(G_OBJECT(textBuffer), "changed", G_CALLBACK(TextEdit_change), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(textBuffer), "notify::cursor-position", G_CALLBACK(TextEdit_move), (gpointer)this);
|
||||
@@ -55,13 +56,16 @@ auto pTextEdit::setBackgroundColor(Color color) -> void {
|
||||
gtk_widget_modify_base(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
}
|
||||
|
||||
auto pTextEdit::setCursorPosition(unsigned position) -> void {
|
||||
auto pTextEdit::setCursor(Cursor cursor) -> void {
|
||||
lock();
|
||||
GtkTextMark* mark = gtk_text_buffer_get_mark(textBuffer, "insert");
|
||||
GtkTextIter iter;
|
||||
gtk_text_buffer_get_end_iter(textBuffer, &iter);
|
||||
gtk_text_iter_set_offset(&iter, min(position, gtk_text_iter_get_offset(&iter)));
|
||||
gtk_text_buffer_place_cursor(textBuffer, &iter);
|
||||
GtkTextIter offset, length;
|
||||
gtk_text_buffer_get_end_iter(textBuffer, &offset);
|
||||
gtk_text_buffer_get_end_iter(textBuffer, &length);
|
||||
signed end = gtk_text_iter_get_offset(&offset);
|
||||
gtk_text_iter_set_offset(&offset, max(0, min(end, cursor.offset())));
|
||||
gtk_text_iter_set_offset(&length, max(0, min(end, cursor.offset() + cursor.length())));
|
||||
gtk_text_buffer_select_range(textBuffer, &offset, &length);
|
||||
auto mark = gtk_text_buffer_get_mark(textBuffer, "insert");
|
||||
gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(subWidget), mark);
|
||||
unlock();
|
||||
}
|
||||
@@ -70,6 +74,10 @@ auto pTextEdit::setEditable(bool editable) -> void {
|
||||
gtk_text_view_set_editable(GTK_TEXT_VIEW(subWidget), editable);
|
||||
}
|
||||
|
||||
auto pTextEdit::setFocused() -> void {
|
||||
gtk_widget_grab_focus(subWidget);
|
||||
}
|
||||
|
||||
auto pTextEdit::setForegroundColor(Color color) -> void {
|
||||
GdkColor gdkColor = CreateColor(color);
|
||||
gtk_widget_modify_text(subWidget, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
|
@@ -7,8 +7,9 @@ struct pTextEdit : pWidget {
|
||||
|
||||
auto focused() const -> bool override;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setCursorPosition(unsigned position) -> void;
|
||||
auto setCursor(Cursor cursor) -> void;
|
||||
auto setEditable(bool editable) -> void;
|
||||
auto setFocused() -> void override;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
auto setWordWrap(bool wordWrap) -> void;
|
||||
|
@@ -3,26 +3,36 @@
|
||||
namespace hiro {
|
||||
|
||||
auto pTreeViewItem::construct() -> void {
|
||||
if(auto parentWidget = _parentWidget()) {
|
||||
if(auto parentItem = _parentItem()) {
|
||||
gtk_tree_store_append(parentWidget->gtkTreeStore, >kIter, &parentItem->gtkIter);
|
||||
} else {
|
||||
gtk_tree_store_append(parentWidget->gtkTreeStore, >kIter, nullptr);
|
||||
}
|
||||
setChecked(state().checked);
|
||||
setImage(state().image);
|
||||
setText(state().text);
|
||||
}
|
||||
}
|
||||
|
||||
auto pTreeViewItem::destruct() -> void {
|
||||
if(auto parent = _parentWidget()) {
|
||||
gtk_tree_store_remove(parent->gtkTreeStore, >kIter);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
auto pTreeViewItem::append(sTreeViewItem item) -> void {
|
||||
if(auto parentWidget = _parentWidget()) {
|
||||
gtk_tree_store_append(parentWidget->gtkTreeStore, &item->self()->gtkIter, >kIter);
|
||||
item->setChecked(item->checked());
|
||||
item->setIcon(item->icon());
|
||||
item->setText(item->text());
|
||||
}
|
||||
}
|
||||
|
||||
auto pTreeViewItem::remove(sTreeViewItem item) -> void {
|
||||
if(auto parentWidget = _parentWidget()) {
|
||||
gtk_tree_store_remove(parentWidget->gtkTreeStore, &item->self()->gtkIter);
|
||||
}
|
||||
}
|
||||
|
||||
auto pTreeViewItem::setBackgroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pTreeViewItem::setCheckable(bool checkable) -> void {
|
||||
}
|
||||
|
||||
auto pTreeViewItem::setChecked(bool checked) -> void {
|
||||
@@ -31,6 +41,18 @@ auto pTreeViewItem::setChecked(bool checked) -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pTreeViewItem::setExpanded(bool expanded) -> void {
|
||||
if(auto parentWidget = _parentWidget()) {
|
||||
auto path = gtk_tree_model_get_path(parentWidget->gtkTreeModel, >kIter);
|
||||
if(expanded) {
|
||||
gtk_tree_view_expand_row(parentWidget->gtkTreeView, path, false);
|
||||
} else {
|
||||
gtk_tree_view_collapse_row(parentWidget->gtkTreeView, path);
|
||||
}
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
}
|
||||
|
||||
auto pTreeViewItem::setFocused() -> void {
|
||||
if(auto parentWidget = _parentWidget()) {
|
||||
GtkTreePath* path = gtk_tree_path_new_from_string(self().path().transform("/", ":"));
|
||||
@@ -40,10 +62,13 @@ auto pTreeViewItem::setFocused() -> void {
|
||||
}
|
||||
}
|
||||
|
||||
auto pTreeViewItem::setIcon(const image& icon) -> void {
|
||||
auto pTreeViewItem::setForegroundColor(Color color) -> void {
|
||||
}
|
||||
|
||||
auto pTreeViewItem::setImage(const Image& image) -> void {
|
||||
if(auto parentWidget = _parentWidget()) {
|
||||
if(icon) {
|
||||
auto pixbuf = CreatePixbuf(icon, true);
|
||||
if(image) {
|
||||
auto pixbuf = CreatePixbuf(image);
|
||||
gtk_tree_store_set(parentWidget->gtkTreeStore, >kIter, 1, pixbuf, -1);
|
||||
} else {
|
||||
gtk_tree_store_set(parentWidget->gtkTreeStore, >kIter, 1, nullptr, -1);
|
||||
|
@@ -7,9 +7,13 @@ struct pTreeViewItem : pObject {
|
||||
|
||||
auto append(sTreeViewItem item) -> void;
|
||||
auto remove(sTreeViewItem item) -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setCheckable(bool checkable) -> void;
|
||||
auto setChecked(bool checked) -> void;
|
||||
auto setExpanded(bool expanded) -> void;
|
||||
auto setFocused() -> void;
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setImage(const Image& image) -> void;
|
||||
auto setSelected() -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
|
@@ -2,10 +2,14 @@
|
||||
|
||||
namespace hiro {
|
||||
|
||||
//gtk_tree_view_collapse_all(gtkTreeView);
|
||||
//gtk_tree_view_expand_all(gtkTreeView);
|
||||
|
||||
static auto TreeView_activate(GtkTreeView*, GtkTreePath* gtkPath, GtkTreeViewColumn*, pTreeView* p) -> void { p->_activatePath(gtkPath); }
|
||||
static auto TreeView_buttonEvent(GtkTreeView*, GdkEventButton* gdkEvent, pTreeView* p) -> signed { return p->_buttonEvent(gdkEvent); }
|
||||
static auto TreeView_change(GtkTreeSelection*, pTreeView* p) -> void { p->_updateSelected(); }
|
||||
static auto TreeView_context(GtkTreeView*, pTreeView* p) -> void { p->self().doContext(); }
|
||||
static auto TreeView_dataFunc(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, pTreeView* p) -> void { return p->_doDataFunc(column, renderer, iter); }
|
||||
static auto TreeView_toggle(GtkCellRendererToggle*, char* path, pTreeView* p) -> void { p->_togglePath(path); }
|
||||
|
||||
auto pTreeView::construct() -> void {
|
||||
@@ -29,15 +33,17 @@ auto pTreeView::construct() -> void {
|
||||
gtkCellToggle = gtk_cell_renderer_toggle_new();
|
||||
gtk_tree_view_column_pack_start(gtkTreeViewColumn, gtkCellToggle, false);
|
||||
gtk_tree_view_column_set_attributes(gtkTreeViewColumn, gtkCellToggle, "active", 0, nullptr);
|
||||
gtk_cell_renderer_set_visible(gtkCellToggle, state().checkable);
|
||||
gtk_tree_view_column_set_cell_data_func(gtkTreeViewColumn, GTK_CELL_RENDERER(gtkCellToggle), (GtkTreeCellDataFunc)TreeView_dataFunc, (gpointer)this, nullptr);
|
||||
|
||||
gtkCellPixbuf = gtk_cell_renderer_pixbuf_new();
|
||||
gtk_tree_view_column_pack_start(gtkTreeViewColumn, gtkCellPixbuf, false);
|
||||
gtk_tree_view_column_set_attributes(gtkTreeViewColumn, gtkCellPixbuf, "pixbuf", 1, nullptr);
|
||||
gtk_tree_view_column_set_cell_data_func(gtkTreeViewColumn, GTK_CELL_RENDERER(gtkCellPixbuf), (GtkTreeCellDataFunc)TreeView_dataFunc, (gpointer)this, nullptr);
|
||||
|
||||
gtkCellText = gtk_cell_renderer_text_new();
|
||||
gtk_tree_view_column_pack_start(gtkTreeViewColumn, gtkCellText, true);
|
||||
gtk_tree_view_column_set_attributes(gtkTreeViewColumn, gtkCellText, "text", 2, nullptr);
|
||||
gtk_tree_view_column_set_cell_data_func(gtkTreeViewColumn, GTK_CELL_RENDERER(gtkCellText), (GtkTreeCellDataFunc)TreeView_dataFunc, (gpointer)this, nullptr);
|
||||
|
||||
gtk_tree_view_append_column(gtkTreeView, gtkTreeViewColumn);
|
||||
gtk_tree_view_set_search_column(gtkTreeView, 2);
|
||||
@@ -63,29 +69,9 @@ auto pTreeView::destruct() -> void {
|
||||
//
|
||||
|
||||
auto pTreeView::append(sTreeViewItem item) -> void {
|
||||
gtk_tree_store_append(gtkTreeStore, &item->self()->gtkIter, nullptr);
|
||||
item->setChecked(item->checked());
|
||||
item->setIcon(item->icon());
|
||||
item->setText(item->text());
|
||||
}
|
||||
|
||||
auto pTreeView::collapse() -> void {
|
||||
gtk_tree_view_collapse_all(gtkTreeView);
|
||||
}
|
||||
|
||||
auto pTreeView::expand() -> void {
|
||||
gtk_tree_view_expand_all(gtkTreeView);
|
||||
}
|
||||
|
||||
auto pTreeView::remove(sTreeViewItem item) -> void {
|
||||
gtk_tree_store_remove(gtkTreeStore, &item->self()->gtkIter);
|
||||
}
|
||||
|
||||
auto pTreeView::reset() -> void {
|
||||
gtk_tree_view_set_model(gtkTreeView, nullptr);
|
||||
gtkTreeStore = gtk_tree_store_new(3, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_STRING);
|
||||
gtkTreeModel = GTK_TREE_MODEL(gtkTreeStore);
|
||||
gtk_tree_view_set_model(gtkTreeView, gtkTreeModel);
|
||||
}
|
||||
|
||||
auto pTreeView::setBackgroundColor(Color color) -> void {
|
||||
@@ -93,10 +79,6 @@ auto pTreeView::setBackgroundColor(Color color) -> void {
|
||||
gtk_widget_modify_base(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
}
|
||||
|
||||
auto pTreeView::setCheckable(bool checkable) -> void {
|
||||
gtk_cell_renderer_set_visible(gtkCellToggle, checkable);
|
||||
}
|
||||
|
||||
auto pTreeView::setForegroundColor(Color color) -> void {
|
||||
auto gdkColor = CreateColor(color);
|
||||
gtk_widget_modify_text(gtkWidgetChild, GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
@@ -136,6 +118,41 @@ auto pTreeView::_buttonEvent(GdkEventButton* gdkEvent) -> signed {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto pTreeView::_doDataFunc(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeIter* iter) -> void {
|
||||
auto path = gtk_tree_model_get_string_from_iter(gtkTreeModel, iter);
|
||||
auto parts = string{path}.split(":");
|
||||
g_free(path);
|
||||
|
||||
auto item = self().item(decimal(parts.takeFirst()));
|
||||
if(!item) return;
|
||||
while(parts) {
|
||||
item = item.item(decimal(parts.takeFirst()));
|
||||
if(!item) return;
|
||||
}
|
||||
|
||||
if(renderer == GTK_CELL_RENDERER(gtkCellToggle)) {
|
||||
gtk_cell_renderer_set_visible(renderer, item->state.checkable);
|
||||
} else if(renderer == GTK_CELL_RENDERER(gtkCellPixbuf)) {
|
||||
gtk_cell_renderer_set_visible(renderer, (bool)item->state.image);
|
||||
} else if(renderer == GTK_CELL_RENDERER(gtkCellText)) {
|
||||
auto font = pFont::create(item->font(true));
|
||||
g_object_set(G_OBJECT(renderer), "font-desc", font, nullptr);
|
||||
pango_font_description_free(font);
|
||||
if(auto color = item->foregroundColor(true)) {
|
||||
auto gdkColor = CreateColor(color);
|
||||
g_object_set(G_OBJECT(renderer), "foreground-gdk", &gdkColor, nullptr);
|
||||
} else {
|
||||
g_object_set(G_OBJECT(renderer), "foreground-set", false, nullptr);
|
||||
}
|
||||
}
|
||||
if(auto color = item->backgroundColor(true)) {
|
||||
auto gdkColor = CreateColor(color);
|
||||
g_object_set(G_OBJECT(renderer), "cell-background-gdk", &gdkColor, nullptr);
|
||||
} else {
|
||||
g_object_set(G_OBJECT(renderer), "cell-background-set", false, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
auto pTreeView::_togglePath(string path) -> void {
|
||||
if(auto item = self().item(path.transform(":", "/"))) {
|
||||
bool checked = !item->checked();
|
||||
|
@@ -6,16 +6,13 @@ struct pTreeView : pWidget {
|
||||
Declare(TreeView, Widget)
|
||||
|
||||
auto append(sTreeViewItem item) -> void;
|
||||
auto collapse() -> void;
|
||||
auto expand() -> void;
|
||||
auto remove(sTreeViewItem item) -> void;
|
||||
auto reset() -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setCheckable(bool checkable) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
|
||||
auto _activatePath(GtkTreePath* gtkPath) -> void;
|
||||
auto _buttonEvent(GdkEventButton* gdkEvent) -> signed;
|
||||
auto _doDataFunc(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeIter* iter) -> void;
|
||||
auto _togglePath(string path) -> void;
|
||||
auto _updateSelected() -> void;
|
||||
|
||||
|
@@ -33,7 +33,7 @@ auto pWidget::setFocused() -> void {
|
||||
gtk_widget_grab_focus(gtkWidget);
|
||||
}
|
||||
|
||||
auto pWidget::setFont(const string& font) -> void {
|
||||
auto pWidget::setFont(const Font& font) -> void {
|
||||
if(!gtkWidget) return;
|
||||
return pFont::setFont(gtkWidget, font);
|
||||
}
|
||||
|
@@ -9,7 +9,7 @@ struct pWidget : pSizable {
|
||||
virtual auto focused() const -> bool override;
|
||||
auto setEnabled(bool enabled) -> void override;
|
||||
virtual auto setFocused() -> void override;
|
||||
auto setFont(const string& font) -> void override;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setGeometry(Geometry geometry) -> void override;
|
||||
auto setVisible(bool visible) -> void override;
|
||||
|
||||
|
@@ -388,7 +388,7 @@ auto pWindow::_setMenuEnabled(bool enabled) -> void {
|
||||
gtk_widget_set_sensitive(gtkMenu, enabled);
|
||||
}
|
||||
|
||||
auto pWindow::_setMenuFont(const string& font) -> void {
|
||||
auto pWindow::_setMenuFont(const Font& font) -> void {
|
||||
pFont::setFont(gtkMenu, font);
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ auto pWindow::_setStatusEnabled(bool enabled) -> void {
|
||||
gtk_widget_set_sensitive(gtkStatus, enabled);
|
||||
}
|
||||
|
||||
auto pWindow::_setStatusFont(const string& font) -> void {
|
||||
auto pWindow::_setStatusFont(const Font& font) -> void {
|
||||
pFont::setFont(gtkStatus, font);
|
||||
}
|
||||
|
||||
|
@@ -29,10 +29,10 @@ struct pWindow : pObject {
|
||||
auto _menuHeight() const -> signed;
|
||||
auto _setIcon(const string& basename) -> bool;
|
||||
auto _setMenuEnabled(bool enabled) -> void;
|
||||
auto _setMenuFont(const string& font) -> void;
|
||||
auto _setMenuFont(const Font& font) -> void;
|
||||
auto _setMenuVisible(bool visible) -> void;
|
||||
auto _setStatusEnabled(bool enabled) -> void;
|
||||
auto _setStatusFont(const string& font) -> void;
|
||||
auto _setStatusFont(const Font& font) -> void;
|
||||
auto _setStatusText(const string& text) -> void;
|
||||
auto _setStatusVisible(bool visible) -> void;
|
||||
auto _statusHeight() const -> signed;
|
||||
|
Reference in New Issue
Block a user