TextView issues



First of all,
sorry, I've not submitted it on bugzilla. I found those issues in our Application and had no time to check if it is GTKMM or GTK issue.

The problems for widget packed into TextView are:
1. Button label is not shown when 've been chaned with same size text.
2. Incorrect frame border redrawing when frame is not fit the textview area horizontally.

Details in attached example.

Regards,
-andrew

RedHat 9
GTK+2.2.3
GTKMM-2.2.7

/*
 * This Program is demonstrating two problems when redrawing widgets
 * that were packed into TextView.
 *
 * Also, it could be used as example of Layout in case when user
 * is going to pack several entry widgets with different size,
 * and he would to allocate minimum space on the screen
 */

#include <gtkmm/main.h>
#include <gtkmm/window.h>
#include <gtkmm/menu.h>
#include <gtkmm/button.h>
#include <gtkmm/image.h>
#include <gtkmm/frame.h>
#include <gtkmm/box.h>
#include <gtkmm/entry.h>
#include <gtkmm/textview.h>
#include <gtkmm/stock.h>
#include <gtkmm/scrolledwindow.h>
#include <iostream>

using namespace std;

static char *text_map[] =
    {
	"==",
	"<>",
	"<",
	"<=",
	">",
	">=",
	0
    };

class TButton : public Gtk::Button
{
public:
   TButton () {}
   ~TButton () {}
protected:
   virtual bool on_expose_event (GdkEventExpose* event)
   {
       // this call is forcing button child to allocate proper space,
       // otherwise label won't be shown on the button
       // I wonder why we need this only in case when our widget is packed
       // into TextView?
       resize_children ();

       return Gtk::Widget::on_expose_event (event);
   }
};

class FilterContainer: public Gtk::Frame
{
    public:
	FilterContainer ();
	virtual ~FilterContainer ();

	void set_kind (int i);
	void raise_options ();
	void init_menu ();
	void toggle_mode (int mode);

    private:
	Gtk::Widget *entry;
/*
 * Aggregating opt_button as TButton class will fix following problem:
 * button label is not shown when you've changed it (use pop-up menu) with
 * same size label (sample: "==" -> "<>")
 * 
	TButton opt_button;
 */
	Gtk::Button opt_button;
	Gtk::Menu menu;
};

FilterContainer::FilterContainer ()
	: Gtk::Frame ("Filter")
    {
	Gtk::HBox *box = Gtk::manage (new Gtk::HBox);
	add (*box);

	opt_button.show_all ();
	set_kind (0);
	opt_button.signal_clicked ().connect
	    (SigC::slot (*this, &FilterContainer::raise_options));
	box->pack_start (opt_button, Gtk::PACK_SHRINK);

	entry = Gtk::manage (new Gtk::Entry);
	box->pack_start (*entry, Gtk::PACK_EXPAND_WIDGET);
	entry->show_all ();

	init_menu ();

	show_all ();
    }

FilterContainer::~FilterContainer ()
{
}

    void FilterContainer::raise_options ()
    {
	menu.popup (1, 0);
    }

    void FilterContainer::toggle_mode (int mode)
    {
	set_kind (mode);
    }

    void FilterContainer::init_menu ()
    {
	Gtk::Menu_Helpers::MenuList items = menu.items ();

	for(unsigned int i = 0; text_map[i]; ++i)
	{
	    items.push_back
		(Gtk::Menu_Helpers::MenuElem
		 (text_map[i],
		  SigC::bind (SigC::slot
			      (*this, &FilterContainer::toggle_mode), i)));
	}
    }

    void FilterContainer::set_kind (int i)
    {
	opt_button.set_label (text_map[i]);
    }

class Filter: public Gtk::Frame
{
    public:
	Filter ();

protected:
   virtual bool button_press_cb (GdkEventButton* event)
   {
       return true;
   }

    private:
	Gtk::TextView text;

	void on_map ();
	void obfuscate_text ();

	FilterContainer * get_widget_for_filter ();
	void add_filter ();
    };

Filter::Filter () : Gtk::Frame ("Layout")
    {
	obfuscate_text ();

	Gtk::ScrolledWindow *scroll = Gtk::manage (new Gtk::ScrolledWindow);
	scroll->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER);
	scroll->add (text);
	add (*scroll);

	show_all_children ();
	add_filter ();
	add_filter ();
    }

    void Filter::on_map ()
    {
	Gtk::Frame::on_map ();

	Glib::RefPtr <Gdk::Window > wnd =
	    text.get_window (Gtk::TEXT_WINDOW_TEXT);

	if ( wnd )
	{
	    wnd->set_cursor (); // set default cursor for textview
	}
	else
	{
	    cout << "ON_MAP: no window" << endl;
	}
    }

    void Filter::obfuscate_text ()
    {
	// using textview as layout for undefined number of widgets
	// to pack into
	Gdk::Color bg ( get_style ()->get_background (Gtk::STATE_NORMAL) );
	text.modify_base (Gtk::STATE_NORMAL, bg);
	text.set_editable ( false );
	text.set_cursor_visible ( false );
	text.set_wrap_mode (Gtk::WRAP_WORD);
	text.set_pixels_inside_wrap (0);
	text.set_indent (0);
/*
 * Remove this comment to fix redrawing of FilterContainer when horizontal
 * scrollbar is present and user just clicked mouse over textview area
 * 
	text.signal_button_press_event ().connect
	    (SigC::slot (*this, &Filter::button_press_cb), false);
 */
    }

    FilterContainer * Filter::get_widget_for_filter ()
    {
	FilterContainer* c = manage (new FilterContainer);
	return c;
    }

    void Filter::add_filter ()
    {
	Glib::RefPtr < Gtk::TextBuffer > refBuffer = text.get_buffer ( );

	Gtk::TextIter iter = refBuffer->end ();
	Glib::RefPtr < Gtk::TextChildAnchor > refAnchor =
	    refBuffer->create_child_anchor ( iter );

	FilterContainer *fc = get_widget_for_filter ();
	text.add_child_at_anchor ( *fc, refAnchor );
	fc->show_all ();
    }

class MyApp : public Gtk::Window
{
public:
   MyApp ()
   {
       Filter *filter = Gtk::manage (new Filter);
       add (*filter);
       show_all_children ();
   }
   ~MyApp ()
   {
   }
};

int main (int argc, char *argv[])
{
    Gtk::Main kit (&argc, &argv);
    MyApp app;
    kit.run (app);
    return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]