📄 whandler.cc
字号:
while (GTK_WIDGET_NO_WINDOW(near)) near = near->parent; gint near_x1, near_y1, near_x2, near_y2; gdk_window_get_origin(near->window, &near_x1, &near_y1); gdk_drawable_get_size(near->window, &near_x2, &near_y2); near_x2 += near_x1, near_y2 += near_y1; // get action area requisition int which = (hi->writable() ? 0 : 1); make_actions(which); GtkRequisition requisition; gtk_widget_size_request(_actions[which], &requisition); // adjust position based on screen gint x, y; if (near_x2 > gdk_screen_get_width(screen)) x = gdk_screen_get_width(screen) - requisition.width; else if (near_x2 - requisition.width < 0) x = 0; else x = near_x2 - requisition.width; if (near_y2 + requisition.height > gdk_screen_get_height(screen)) { if (near_y1 - requisition.height < 0) y = 0; else y = near_y1 - requisition.height; } else y = near_y2; gtk_window_move(GTK_WINDOW(_actions[which]), x, y); gtk_widget_show(_actions[which]);}void whandler::hide_actions(const String &hname, bool restore){ if (!hname || hname == _actions_hname) { if (_actions[0]) gtk_widget_hide(_actions[0]); if (_actions[1]) gtk_widget_hide(_actions[1]); hinfo *hi = find_hinfo(_actions_hname); if (!hi || !hi->editable() || !active()) return; // remember checkbox state handler_value *hv = hi->hv; if ((hv->flags() & hflag_checkbox) && restore) { GtkToggleButton *b = GTK_TOGGLE_BUTTON(hi->wdata); bool value; if (cp_bool(hv->hvalue(), &value)) { _updating++; gtk_toggle_button_set_active(b, value); _updating--; } else gtk_toggle_button_set_inconsistent(b, TRUE); } // unbold label on empty handlers if (hv->write_only() || hv->read_param()) { bool empty = false; if (GTK_IS_ENTRY(hi->wdata)) empty = (strlen(gtk_entry_get_text(GTK_ENTRY(hi->wdata))) == 0); else if (GTK_IS_TEXT_VIEW(hi->wdata)) { GtkTextBuffer *b = gtk_text_view_get_buffer(GTK_TEXT_VIEW(hi->wdata)); empty = (gtk_text_buffer_get_char_count(b) == 0); } if (empty) { hi->set_edit_active(_rw, false); hi->hv->clear_hvalue(); } } _actions_hname = String(); _actions_changed = false; }}void whandler::apply_action(const String &action_for, bool activate){ if (active()) { hinfo *hi = find_hinfo(action_for); if (!hi || !hi->editable()) return; int which = (hi->writable() ? 0 : 1); if (activate) g_signal_emit_by_name(G_OBJECT(_actions_apply[which]), "activate"); const gchar *data; gchar *data_free = 0; if (hi->hv->flags() & hflag_button) data = ""; else if (hi->hv->flags() & hflag_checkbox) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(hi->wdata))) data = "true"; else data = "false"; } else if (GTK_IS_TEXT_VIEW(hi->wdata)) { GtkTextIter i1, i2; GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(hi->wdata)); gtk_text_buffer_get_start_iter(buffer, &i1); gtk_text_buffer_get_end_iter(buffer, &i2); data_free = gtk_text_buffer_get_text(buffer, &i1, &i2, FALSE); data = data_free; } else if (GTK_IS_ENTRY(hi->wdata)) data = gtk_entry_get_text(GTK_ENTRY(hi->wdata)); else data = ""; assert(_rw->driver()); if (hi->writable()) { _rw->driver()->do_write(action_for, data, 0); hi->hv->clear_hvalue(); if (hi->hv->refreshable()) hi->hv->refresh(main()); } else _rw->driver()->do_read(action_for, data, 0); hide_actions(action_for, false); if (data_free) g_free(data_free); }}extern "C" {static void on_handler_read_notify(GObject *obj, GParamSpec *, gpointer user_data){ GtkExpander *expander = GTK_EXPANDER(obj); const gchar *hname = whandler::widget_hname(GTK_WIDGET(expander)); whandler *wh = reinterpret_cast<whandler *>(user_data); if (gtk_expander_get_expanded(expander)) wh->refresh(hname, false);}static gboolean on_handler_event(GtkWidget *w, GdkEvent *event, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); const gchar *hname = whandler::widget_hname(w); if ((event->type == GDK_FOCUS_CHANGE && !event->focus_change.in) || (event->type == GDK_KEY_PRESS && event->key.keyval == GDK_Escape)) wh->hide_actions(hname); else if ((event->type == GDK_KEY_PRESS && event->key.keyval == GDK_Return) || (event->type == GDK_KEY_PRESS && event->key.keyval == GDK_ISO_Enter)) { if (GTK_IS_ENTRY(w)) wh->apply_action(hname, true); } else if (event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) wh->show_actions(w, hname, false); return FALSE;}static void on_handler_check_button_toggled(GtkToggleButton *tb, gpointer user_data){ const gchar *hname = whandler::widget_hname(GTK_WIDGET(tb)); reinterpret_cast<whandler *>(user_data)->show_actions(GTK_WIDGET(tb), hname, true);}static void on_handler_entry_changed(GObject *obj, GParamSpec *, gpointer user_data){ const gchar *hname = whandler::widget_hname(GTK_WIDGET(obj)); whandler *wh = reinterpret_cast<whandler *>(user_data); wh->show_actions(GTK_WIDGET(obj), hname, true);}static void on_handler_text_buffer_changed(GtkTextBuffer *buffer, gpointer user_data){ GtkWidget *view = (GtkWidget *) g_object_get_data(G_OBJECT(buffer), "clicky_view"); const gchar *hname = whandler::widget_hname(view); whandler *wh = reinterpret_cast<whandler *>(user_data); wh->show_actions(view, hname, true);}static void on_handler_action_cancel_clicked(GtkButton *, gpointer user_data){ reinterpret_cast<whandler *>(user_data)->hide_actions();}static void on_handler_action_apply_clicked(GtkButton *button, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); const gchar *hname = whandler::widget_hname(GTK_WIDGET(button)); String hstr = (hname ? String(hname) : wh->active_action()); wh->apply_action(hstr, false);}}void whandler::refresh(const String &hname, bool always){ hinfo *hi = find_hinfo(hname); if (hi && (always || !hi->hv->have_hvalue())) hi->hv->refresh(_rw);}/** @brief Read all read handlers and reset all write-only handlers. */void whandler::refresh_all(bool always){ for (std::deque<hinfo>::iterator hi = _hinfo.begin(); hi != _hinfo.end(); ++hi) { handler_value *hv = hi->hv; if (hv->refreshable() && hv->have_required_hparam() && (always || !hv->have_hvalue())) hi->hv->refresh(_rw); else if (hv->write_only() && _actions_hname != hv->hname()) hi->display(this, false); }}void whandler::notify_read(handler_value *hv){ hinfo *hi = find_hinfo(hv); if (hi && hv->readable() && hv->visible()) { _updating++; hi->display(this, true); _updating--; } else if (hv->hname().length() == _display_ename.length() + 9 && memcmp(hv->hname().begin(), _display_ename.begin(), _display_ename.length()) == 0 && memcmp(hv->hname().end() - 9, ".handlers", 9) == 0) display(_display_ename, false);}void whandler::notify_write(const String &hname, const String &, int status){ hinfo *hi = find_hinfo(hname); if (hi && hi->writable()) { _updating++; if (!hi->readable() && status < 300) hi->display(this, false); _updating--; }}/***** * * Handler preferences * */void whandler::set_hinfo_flags(const String &hname, int flags, int flag_values){ if (hinfo *hi = find_hinfo(hname)) { hi->hv->set_flags(main(), (hi->hv->flags() & ~flags) | flag_values); //if (flags & hflag_notify_delt) // main()->diagram()->hpref_apply(hi->hv); }}void whandler::set_hinfo_autorefresh_period(const String &hname, int period){ if (hinfo *hi = find_hinfo(hname)) hi->hv->set_autorefresh_period(period > 0 ? period : 1);}extern "C" {static void on_hpref_visible_toggled(GtkToggleButton *button, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); const gchar *hname = whandler::widget_hname(GTK_WIDGET(button)); gboolean on = gtk_toggle_button_get_active(button); wh->set_hinfo_flags(hname, hflag_visible, on ? hflag_visible : 0); GtkWidget *widget = reinterpret_cast<GtkWidget *>(g_object_get_data(G_OBJECT(button), "clicky_hider")); if (on) gtk_widget_show(widget); else gtk_widget_hide(widget);}static void on_hpref_refreshable_toggled(GtkToggleButton *button, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); const gchar *hname = whandler::widget_hname(GTK_WIDGET(button)); gboolean on = gtk_toggle_button_get_active(button); wh->set_hinfo_flags(hname, hflag_refresh, on ? hflag_refresh : 0);}static void on_hpref_autorefresh_toggled(GtkToggleButton *button, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); const gchar *hname = whandler::widget_hname(GTK_WIDGET(button)); gboolean on = gtk_toggle_button_get_active(button); wh->set_hinfo_flags(hname, hflag_autorefresh, on ? hflag_autorefresh : 0); GtkWidget *widget = reinterpret_cast<GtkWidget *>(g_object_get_data(G_OBJECT(button), "clicky_hider")); if (on) gtk_widget_show(widget); else gtk_widget_hide(widget);}static void on_hpref_autorefresh_value_changed(GtkSpinButton *button, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); const gchar *hname = whandler::widget_hname(GTK_WIDGET(button)); wh->set_hinfo_autorefresh_period(hname, (guint) (gtk_spin_button_get_value(button) * 1000));}static void on_hpref_preferences_clicked(GtkButton *, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); wh->on_preferences(whandler::onpref_showpref);}static void on_hpref_ok_clicked(GtkButton *, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); wh->on_preferences(whandler::onpref_prefok);}static void on_hpref_cancel_clicked(GtkButton *, gpointer user_data){ whandler *wh = reinterpret_cast<whandler *>(user_data); wh->on_preferences(whandler::onpref_prefcancel);}}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -