📄 whandler.cc
字号:
#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <click/config.h>#include "whandler.hh"#include "cdriver.hh"#include <gdk/gdkkeysyms.h>#include <click/confparse.hh>extern "C" {#include "interface.h"#include "support.h"}namespace clicky {/***** * * handler window * */extern "C" {static gboolean on_handler_event(GtkWidget *, GdkEvent *, gpointer);static void on_handler_read_notify(GObject *, GParamSpec *, gpointer);static void on_handler_entry_changed(GObject *, GParamSpec *, gpointer);static void on_handler_text_buffer_changed(GtkTextBuffer *, gpointer);static void on_handler_check_button_toggled(GtkToggleButton *, gpointer);static void on_handler_action_apply_clicked(GtkButton *, gpointer);static void on_handler_action_cancel_clicked(GtkButton *, gpointer);static void on_hpref_visible_toggled(GtkToggleButton *, gpointer);static void on_hpref_refreshable_toggled(GtkToggleButton *, gpointer);static void on_hpref_autorefresh_toggled(GtkToggleButton *, gpointer);static void on_hpref_autorefresh_value_changed(GtkSpinButton *, gpointer);static void on_hpref_preferences_clicked(GtkButton *, gpointer);static void on_hpref_ok_clicked(GtkButton *, gpointer);static void on_hpref_cancel_clicked(GtkButton *, gpointer);static void destroy_callback(GtkWidget *w, gpointer) { gtk_widget_destroy(w);}}const char *whandler::widget_hname(GtkWidget *w){ for (; w; w = w->parent) if (gpointer x = g_object_get_data(G_OBJECT(w), "clicky_hname")) return reinterpret_cast<gchar *>(x); return 0;}whandler::whandler(wmain *rw) : _rw(rw), _hpref_actions(0), _actions_changed(false), _updating(0){ _eviewbox = lookup_widget(_rw->_window, "eviewbox"); _handlerbox = GTK_BOX(lookup_widget(_rw->_window, "eview_handlerbox")); // config handler entry is always there, thus special _eview_config = lookup_widget(_rw->_window, "eview_config"); g_object_set_data_full(G_OBJECT(_eview_config), "clicky_hname", g_strdup(""), g_free); g_signal_connect(_eview_config, "event", G_CALLBACK(on_handler_event), this); GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(_eview_config)); g_signal_connect(buffer, "changed", G_CALLBACK(on_handler_text_buffer_changed), this); g_object_set_data(G_OBJECT(buffer), "clicky_view", _eview_config); _actions[0] = _actions[1] = 0; _actions_apply[0] = _actions_apply[1] = 0;}whandler::~whandler(){}void whandler::clear(){ _hinfo.clear(); _display_ename = String();}/***** * * Per-hander widget settings * */void whandler::recalculate_positions(){ int pos = 0; for (std::deque<hinfo>::iterator iter = _hinfo.begin(); iter != _hinfo.end(); ++iter) { iter->wposition = pos; if (iter->hv->flags() & (hflag_visible | hflag_preferences)) ++pos; }}int whandler::hinfo::create_preferences(whandler *wh){ int flags = _old_flags = hv->flags(); _old_autorefresh_period = hv->autorefresh_period(); assert((flags & hflag_preferences) && !wcontainer && !wlabel && !wdata); // set up the frame wcontainer = gtk_frame_new(NULL); wlabel = gtk_label_new(hv->handler_name().c_str()); gtk_label_set_attributes(GTK_LABEL(wlabel), wh->main()->small_attr()); gtk_misc_set_alignment(GTK_MISC(wlabel), 0, 0.5); gtk_misc_set_padding(GTK_MISC(wlabel), 2, 0); gtk_frame_set_label_widget(GTK_FRAME(wcontainer), wlabel); GtkWidget *aligner = gtk_alignment_new(0, 0, 1, 1); gtk_alignment_set_padding(GTK_ALIGNMENT(aligner), 0, 4, 2, 2); gtk_container_add(GTK_CONTAINER(wcontainer), aligner); g_object_set_data_full(G_OBJECT(aligner), "clicky_hname", g_strdup(hv->hname().c_str()), g_free); // fill the dialog GtkWidget *mainbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(aligner), mainbox); GtkWidget *w = gtk_check_button_new_with_label(_("Visible")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (flags & hflag_visible)); gtk_box_pack_start(GTK_BOX(mainbox), w, FALSE, FALSE, 0); g_signal_connect(w, "toggled", G_CALLBACK(on_hpref_visible_toggled), wh); GtkWidget *visiblebox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(mainbox), visiblebox, FALSE, FALSE, 0); g_object_set_data(G_OBJECT(w), "clicky_hider", visiblebox); GtkWidget *autorefresh_period = 0; if (flags & hflag_r) { w = gtk_check_button_new_with_label(_("Refreshable")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (flags & hflag_refresh)); gtk_box_pack_start(GTK_BOX(visiblebox), w, FALSE, FALSE, 0); g_signal_connect(w, "toggled", G_CALLBACK(on_hpref_refreshable_toggled), wh); if (flags & hflag_rparam) { // XXX add a text widget for refresh data } // autorefresh w = gtk_check_button_new_with_label(_("Autorefresh")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (flags & hflag_autorefresh)); gtk_box_pack_start(GTK_BOX(visiblebox), w, FALSE, FALSE, 0); g_signal_connect(w, "toggled", G_CALLBACK(on_hpref_autorefresh_toggled), wh); autorefresh_period = gtk_hbox_new(FALSE, 0); g_object_set_data(G_OBJECT(w), "clicky_hider", autorefresh_period); GtkAdjustment *adj = (GtkAdjustment *) gtk_adjustment_new(hv->autorefresh_period() / 1000., 0.01, 60, 0.01, 0.5, 0); GtkWidget *spin = gtk_spin_button_new(adj, 0.01, 3); gtk_box_pack_start(GTK_BOX(autorefresh_period), spin, FALSE, FALSE, 0); g_signal_connect(spin, "value-changed", G_CALLBACK(on_hpref_autorefresh_value_changed), wh); GtkWidget *label = gtk_label_new(_(" sec period")); gtk_box_pack_start(GTK_BOX(autorefresh_period), label, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(visiblebox), autorefresh_period, FALSE, FALSE, 0); } // diagram may be interested // wh->main()->diagram()->hpref_widgets(hv, mainbox); // return gtk_widget_show_all(wcontainer); if ((flags & (hflag_r | hflag_autorefresh)) != (hflag_r | hflag_autorefresh) && autorefresh_period) gtk_widget_hide(autorefresh_period); if (!(flags & hflag_visible)) gtk_widget_hide(visiblebox); return 0;}int whandler::hinfo::create_display(whandler *wh){ int flags = hv->flags(); assert(!(flags & hflag_preferences) && !wdata); // create container if (wcontainer) /* do not recreate */; else if (flags & hflag_collapse) { wcontainer = gtk_expander_new(NULL); if ((flags & hflag_r) != 0 && (flags & hflag_have_hvalue) == 0) g_signal_connect(wcontainer, "notify::expanded", G_CALLBACK(on_handler_read_notify), wh); } else if (flags & (hflag_button | hflag_checkbox)) wcontainer = gtk_hbox_new(FALSE, 0); else wcontainer = gtk_vbox_new(FALSE, 0); // create label if ((flags & hflag_collapse) || !(flags & (hflag_button | hflag_checkbox))) { wlabel = gtk_label_new(hv->handler_name().c_str()); gtk_label_set_attributes(GTK_LABEL(wlabel), wh->main()->small_attr()); if (!(flags & hflag_collapse)) gtk_label_set_ellipsize(GTK_LABEL(wlabel), PANGO_ELLIPSIZE_END); gtk_misc_set_alignment(GTK_MISC(wlabel), 0, 0.5); gtk_widget_show(wlabel); if (flags & hflag_collapse) gtk_expander_set_label_widget(GTK_EXPANDER(wcontainer), wlabel); else gtk_box_pack_start(GTK_BOX(wcontainer), wlabel, FALSE, FALSE, 0); } // create data widget GtkWidget *wadd; int padding = 0; gboolean expand = FALSE; if (flags & hflag_button) { wadd = wdata = gtk_button_new_with_label(hv->handler_name().c_str()); if (!hv->editable()) gtk_widget_set_sensitive(wdata, FALSE); else if (wh->active()) g_signal_connect(wdata, "clicked", G_CALLBACK(on_handler_action_apply_clicked), wh); padding = 2; } else if (flags & hflag_checkbox) { wadd = gtk_event_box_new(); wdata = gtk_check_button_new_with_label(hv->handler_name().c_str()); if (!hv->editable()) gtk_widget_set_sensitive(wdata, FALSE); else if (wh->active()) { g_signal_connect(wdata, "toggled", G_CALLBACK(on_handler_check_button_toggled), wh); gtk_widget_add_events(wdata, GDK_FOCUS_CHANGE_MASK); g_signal_connect(wdata, "event", G_CALLBACK(on_handler_event), wh); } expand = TRUE; gtk_container_add(GTK_CONTAINER(wadd), wdata); gtk_widget_show(wdata); // does nothing yet } else if (flags & hflag_multiline) { wadd = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(wadd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(wadd), GTK_SHADOW_IN); GtkTextBuffer *buffer = gtk_text_buffer_new(wh->main()->binary_tag_table()); wdata = gtk_text_view_new_with_buffer(buffer); g_object_set_data(G_OBJECT(buffer), "clicky_view", wdata); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(wdata), GTK_WRAP_WORD); gtk_widget_show(wdata); gtk_container_add(GTK_CONTAINER(wadd), wdata); if (!editable()) { gtk_text_view_set_editable(GTK_TEXT_VIEW(wdata), FALSE); g_object_set(wdata, "can-focus", FALSE, (const char *) NULL); } else if (wh->active()) { g_signal_connect(wdata, "event", G_CALLBACK(on_handler_event), wh); g_signal_connect(buffer, "changed", G_CALLBACK(on_handler_text_buffer_changed), wh); } } else { wadd = wdata = gtk_entry_new(); if (!hv->editable()) { gtk_entry_set_editable(GTK_ENTRY(wdata), FALSE); g_object_set(wdata, "can-focus", FALSE, (const char *) NULL); } else if (wh->active()) { g_signal_connect(wdata, "event", G_CALLBACK(on_handler_event), wh); g_signal_connect(wdata, "notify::text", G_CALLBACK(on_handler_entry_changed), wh); } } g_object_set_data_full(G_OBJECT(wcontainer), "clicky_hname", g_strdup(hv->hname().c_str()), g_free); gtk_widget_show(wadd); if (flags & hflag_collapse) gtk_container_add(GTK_CONTAINER(wcontainer), wadd); else gtk_box_pack_start(GTK_BOX(wcontainer), wadd, expand, expand, 0); return padding;}void whandler::hinfo::create(whandler *wh, int new_flags, bool always_position){ if (hv->flags() & hflag_special) return; // don't flash the expander if (wcontainer && (((hv->flags() & new_flags) & (hflag_collapse | hflag_visible)) == (hflag_collapse | hflag_visible)) && (hv->flags() & hflag_preferences) == 0 && (new_flags & hflag_preferences) == 0) { gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(wcontainer))); wdata = 0; } else if (wcontainer) { gtk_widget_destroy(wcontainer); wcontainer = wlabel = wdata = 0; } else assert(wcontainer == 0 && wlabel == 0 && wdata == 0); // set flags, potentially recalculate positions bool recalc = ((hv->flags() ^ new_flags) & (hflag_visible | hflag_preferences)); hv->set_flags(wh->main(), new_flags); if (recalc || always_position) wh->recalculate_positions(); // create the body int padding; if (hv->flags() & hflag_preferences) padding = create_preferences(wh); else if (hv->flags() & hflag_visible) padding = create_display(wh); else return; // add to the container if (!wcontainer->parent) { gtk_box_pack_start(wh->handler_box(), wcontainer, FALSE, FALSE, padding); gtk_box_reorder_child(wh->handler_box(), wcontainer, wposition); gtk_widget_show(wcontainer); } // display contents if visible if ((hv->flags() & (hflag_preferences | hflag_visible)) == hflag_visible) { wh->_updating++; display(wh, true); wh->_updating--; }}bool binary_to_utf8(const String &data, StringAccum &text, Vector<int> &positions){ static const char hexdigits[] = "0123456789ABCDEF"; const char *last = data.begin(); bool multiline = false; for (const char *s = data.begin(); s != data.end(); s++) if ((unsigned char) *s > 126 || ((unsigned char) *s < 32 && !isspace((unsigned char) *s))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -