1# abstract_optionsbar.py
2#
3# Copyright 2018-2021 Romain F. T.
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18from gi.repository import Gtk
19
20RSRC_PREFIX = '/com/github/maoschanz/drawing/optionsbars/'
21
22class AbstractOptionsBar():
23	__gtype_name__ = 'AbstractOptionsBar'
24
25	def __init__(self):
26		# Quite high as a precaution, will be more precise later
27		self._limit_size = 700
28		self._is_narrow = False
29
30	def _build_ui(self, end_of_path):
31		"""Creates a Gtk.Builder for the resource whose path is hinted in the
32		method parameter, and tries to extract usual widgets ids from it. Most
33		resulting widgets can be `None`, except `action_bar`. The builder is
34		returned if the caller wants to extract more objects from it.
35		This is valid for any instance of `AbstractOptionsBar`."""
36		builder = Gtk.Builder.new_from_resource(RSRC_PREFIX + end_of_path)
37		self.action_bar = builder.get_object('bottom-pane')
38		self.cancel_btn = builder.get_object('cancel_btn') # may be None
39		self.centered_box = builder.get_object('centered_box') # may be None
40		self.apply_btn = builder.get_object('apply_btn') # may be None
41		self.help_btn = builder.get_object('help_btn') # may be None
42		self.options_btn = builder.get_object('options_btn') # may be None
43		self._togglable_btn = self.options_btn # default value, may change later
44		return builder # for implementations-specific widgets
45
46	def _hydrate_transform_tool(self, end_of_path):
47		"""Same as above, BUT this isn't valid for any instance of
48		`AbstractOptionsBar`: only an optionsbar for a transform tool should
49		call that method, and it should call it *after* `_build_ui`. This method
50		will "hydrate" the previously built (but still incomplete) widgets."""
51		builder = Gtk.Builder.new_from_resource(RSRC_PREFIX + end_of_path)
52		self.centered_box = builder.get_object('centered_box')
53		self.action_bar.set_center_widget(self.centered_box)
54		actions_menu = builder.get_object('actions-menu')
55		if actions_menu:
56			self.options_btn.set_menu_model(actions_menu)
57		else:
58			self.options_btn.destroy()
59			self.options_btn = None
60		return builder
61
62	def build_options_menu(self, widget, model, label):
63		"""Set a widget (or a menu) as the popover with tools options. In
64		practice this is used only with the classic tools' pane, and all classic
65		tools provide a menu instead of a widget."""
66		pass
67
68	def update_for_new_tool(self, tool):
69		"""Update the pane when a tool using it has just been activated. Widgets
70		may be hidden/shown or enabled/disabled depending on the properties of
71		the given tool."""
72		pass
73
74	def get_minimap_btn(self):
75		pass
76
77	def set_minimap_label(self, label):
78		pass
79
80	def toggle_options_menu(self):
81		if self._togglable_btn and self._togglable_btn.get_visible():
82			self._togglable_btn.set_active(not self._togglable_btn.get_active())
83
84	def hide_options_menu(self):
85		if self._togglable_btn:
86			self._togglable_btn.set_active(False)
87
88	def middle_click_action(self):
89		pass
90
91	def init_adaptability(self):
92		"""Instructions to run during the first window size allocation (and only
93		the first). Calling this is managed by the window's `DrOptionsManager`.
94		It estimates the minimal amount of pixels for the mobile version, and
95		gives it to the `_set_limit_size` method.
96		Any implementation HAS TO end with a call to `_set_limit_size`!"""
97		self.set_compact(False)
98		self.action_bar.show_all()
99		# + implementation-specific instructions
100
101	def _set_limit_size(self, temp_limit_size):
102		self._limit_size = int(1.25 * temp_limit_size)
103		self.set_compact(True)
104
105	def adapt_to_window_size(self, allocated_width):
106		"""Check whether or not the costly `set_compact` method should be
107		called, depending on a given window width, and the pane's limit
108		previously set."""
109		can_expand = (allocated_width > self._limit_size)
110		incoherent = (can_expand == self._is_narrow)
111		if incoherent:
112			self.set_compact(not self._is_narrow)
113
114	def set_compact(self, state):
115		"""The parameter is a boolean telling if the bottom pane should become
116		compact or not."""
117		self._is_narrow = state
118		if self.help_btn is not None:
119			self.help_btn.set_visible(not state)
120		# + implementation-specific instructions
121
122	############################################################################
123################################################################################
124
125