https://github.com/mirefek/geo_logic
Tip revision: c8c9b715cae0acfb07585c25659b1333d075cc5b authored by mirefek on 25 July 2021, 19:43:55 UTC
bugfix
bugfix
Tip revision: c8c9b71
toolbar.py
import gi as gtk_import
gtk_import.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk
from gtool_general import GToolGeneral
"""
The GUI element at the top of the window
"""
### Tool Entry with completion
class SelectionEntry(Gtk.Entry):
def __init__(self, options, *args, **kwargs):
Gtk.Entry.__init__(self, *args, **kwargs)
# functions that can be set from outside
self.on_confirm_hook = None # when pressing enter
self.on_discard_hook = None # when loosing focus (escape)
self.on_focus_hook = None # when focus is received
# functions that must be set from outside
self.put_focus_away = None # when the entry wants to get rid of focus
self.connect("activate", self.on_activate)
self.connect("focus-in-event", self.on_focus_in)
self.connect("focus-out-event", self.on_focus_out)
self.connect("key-press-event", self.on_key_press)
self.set_options(options)
self._last_text = ""
self._focus_out_mode = 0
def set_options(self, options):
self.options = list(options)
self.options_s = set(options)
liststore = Gtk.ListStore(str)
self.completion = Gtk.EntryCompletion()
self.set_completion(self.completion)
self.completion.set_text_column(0)
self.completion.set_model(liststore)
prefixes = set()
for option in options:
liststore.append([option])
for i in range(len(option)+1):
prefixes.add(option[:i])
def match_func(completion, key_string, it, data):
model = completion.get_model()
modelstr = model[it][0]
if key_string in prefixes: # there are available completions
return modelstr.startswith(key_string)
else: # search more generally
return key_string in modelstr
self.completion.set_match_func(match_func, None)
self.completion.set_inline_completion(True)
self.completion.set_popup_single_match(True)
self.completion.connect("match-selected", self.on_completion_match)
def on_completion_match(self, completion, model, it):
self.set_text(model[it][0])
self.activate()
return True
def on_activate(self, *args):
text = self.get_text()
if text not in self.options_s: return
self.unselect(2)
if self.on_confirm_hook is not None:
self.on_confirm_hook(text)
def on_focus_in(self, *args):
self._last_text = self.get_text()
if self.on_focus_hook is not None:
self.on_focus_hook()
def on_focus_out(self, *args):
self.select_region(0,0)
if self._focus_out_mode != 2:
self.set_text(self._last_text)
if self._focus_out_mode == 0:
if self.on_discard_hook is not None:
self.on_discard_hook()
self._focus_out_mode = 0
def on_key_press(self,w,e):
keyval = e.keyval
keyval_name = Gdk.keyval_name(keyval)
if keyval_name == "Escape":
self.unselect()
return True
elif keyval_name == "Tab":
bounds = self.get_selection_bounds()
if bounds:
a,b = bounds
self.select_region(b,b)
else: self.completion.complete()
return True
return False
def select(self):
if not self.is_focus():
self.grab_focus()
return True
else: return False
def unselect(self, mode = 0):
self._focus_out_mode = mode
if self.is_focus():
self._use_out_hook = True
self.put_focus_away()
return True
return False
def get_current_option(self):
text = self.get_text()
if text in self.options_s: return text
else: return None
### The main class
class ToolBar(Gtk.HBox):
def __init__(self, menu_items, gtools, gtool_dict):
Gtk.HBox.__init__(self)
self.accelerators = Gtk.AccelGroup()
self.change_tool_hook = None
#### Menu
menu_button = Gtk.MenuButton()
self.pack_start(menu_button, False, False, 0)
menu = Gtk.Menu()
menu_button.set_popup(menu)
def f_capsule(action):
def gtk_action(widget):
action()
return gtk_action
for label, action, accel in menu_items:
item = Gtk.MenuItem.new_with_label(label)
menu.append(item)
item.connect("activate", f_capsule(action))
if accel is not None:
key, mod = Gtk.accelerator_parse(accel)
item.add_accelerator(
"activate", self.accelerators,
key, mod, Gtk.AccelFlags.VISIBLE
)
item.show()
#### Tools
self.toolbox = Gtk.HBox()
self.pack_end(self.toolbox, False, False, 0)
self.first_radio = None
self.tool_to_button = dict()
for gtool in gtools:
icon_name = gtool.get_icon_name()
icon = Gtk.Image.new_from_file(
"images/icons/{}.png".format(icon_name))
label = gtool.get_label()
button = self.add_radio_button(icon, label)
button.connect("toggled", self.tool_button_click, gtool)
self.tool_to_button[gtool] = button
self.other_tool_button = self.add_radio_button(
"view-more", "Other tool (Enter)")
self.other_tool_button.connect(
"toggled", self.other_tool_button_click)
self.gtool = gtools[0]
#### Entry
self.gtool_dict = gtool_dict
names = sorted(gtool_dict.name_to_prefixes.keys())
self.entry = SelectionEntry(names)
self.toolbox.pack_start(self.entry, False, False, 0)
def entry_confirm(name):
tool = gtool_dict.make_tool(name)
self.change_tool(tool)
def entry_focus():
if self.gtool is not None: self.pre_entry_tool = self.gtool
self.other_tool_button.set_active(True)
self.change_tool(None)
def entry_discard():
self.select_tool_button(self.pre_entry_tool)
self.entry.on_confirm_hook = entry_confirm
self.entry.on_focus_hook = entry_focus
self.entry.on_discard_hook = entry_discard
# add a tool
def add_radio_button(self, icon, label):
if self.first_radio is None:
self.first_radio = Gtk.RadioToolButton()
button = self.first_radio
else: button = Gtk.RadioToolButton.new_from_widget(self.first_radio)
if isinstance(icon, str): button.set_icon_name(icon)
else: button.set_icon_widget(icon)
button.set_tooltip_text(label)
self.toolbox.pack_start(button, False, False, 0)
return button
# click on a tool
def tool_button_click(self, button, tool):
if not button.get_active(): return
self.change_tool(tool)
self.entry.unselect(1)
# click on the three dots (entry tool)
def other_tool_button_click(self, button):
if not button.get_active(): return
name = self.entry.get_current_option()
if name is None:
self.entry.select()
return
tool = self.gtool_dict.make_tool(name)
self.change_tool(tool)
def set_entry_unselect(self, f):
self.entry.put_focus_away = f
def select_tool_button(self, tool):
if tool is None: return
if isinstance(tool, GToolGeneral):
self.entry.set_text(tool.name)
self.other_tool_button.set_active(True)
else:
button = self.tool_to_button.get(tool, None)
button.set_active(True)
self.change_tool(tool)
def change_tool(self, tool):
self.gtool = tool
if self.change_tool_hook is not None:
self.change_tool_hook(tool)