mirror of https://github.com/KLayout/klayout.git
Updating samples to include focus pages
This commit is contained in:
parent
b9115fc0a2
commit
b3123d385a
|
|
@ -8,29 +8,39 @@
|
|||
<shortcut></shortcut>
|
||||
<interpreter>ruby</interpreter>
|
||||
<text># Sample plugin
|
||||
#
|
||||
|
||||
# This plugin implements a box that can be drawn by
|
||||
# clicking at the first and then at the second point.
|
||||
# There is one box which is replacing the previous one.
|
||||
# Line color and line width of the box can be configured
|
||||
# by editor options (line width) or configuration pages
|
||||
# (color).
|
||||
# (color). These settings are managed through configuration
|
||||
# options and their current state is persisted.
|
||||
#
|
||||
# The dimension of the box can be entered numerically
|
||||
# while dragging the box. This feature is implemented
|
||||
# through a modal "focus page", which opens when you
|
||||
# press the Tab key during editing and when the keyboard
|
||||
# focus is on the canvas.
|
||||
#
|
||||
# Register this macro as "autorun" to enable the plugin
|
||||
# on startup.
|
||||
|
||||
module DragBox
|
||||
|
||||
# Register this macro as "autorun" to enable the plugin
|
||||
|
||||
CFG_COLOR = "drag-box-color"
|
||||
CFG_WIDTH = "drag-box-width"
|
||||
|
||||
# The widget placed into the editor options dock
|
||||
# An option page providing a single entry box for configuring the line width
|
||||
# This page communicates via configuration options. One advantage of this
|
||||
# approach is that the values are persisted
|
||||
|
||||
class DragBoxEditorOptionsPage < RBA::EditorOptionsPage
|
||||
|
||||
# Creates a new page with title "Options" and at position 1 (second from left)
|
||||
|
||||
def initialize
|
||||
|
||||
# Creates a new page with title "Options" and at
|
||||
# position 1 (second from left)
|
||||
|
||||
super("Options", 1)
|
||||
|
||||
layout2 = RBA::QVBoxLayout::new(self)
|
||||
|
|
@ -44,10 +54,15 @@ class DragBoxEditorOptionsPage < RBA::EditorOptionsPage
|
|||
layout.addWidget(@spin_box)
|
||||
layout.addStretch(1)
|
||||
layout2.addStretch(1)
|
||||
|
||||
# connect the spin box value change with the "edited" slot
|
||||
# which will result in a call of "apply".
|
||||
@spin_box.valueChanged = lambda { |x| self.edited }
|
||||
|
||||
end
|
||||
|
||||
# "setup" is called when the page needs to be populated with information -
|
||||
# i.e. on first show.
|
||||
def setup(dispatcher)
|
||||
begin
|
||||
@spin_box.setValue(dispatcher.get_config(CFG_WIDTH).to_i)
|
||||
|
|
@ -56,23 +71,123 @@ class DragBoxEditorOptionsPage < RBA::EditorOptionsPage
|
|||
end
|
||||
end
|
||||
|
||||
# "apply" is called when the page is requested to submit the entered
|
||||
# values to the plugin. Usually this should be done via configuration
|
||||
# events.
|
||||
def apply(dispatcher)
|
||||
dispatcher.set_config(CFG_WIDTH, @spin_box.value.to_s)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# The widget placed into the configuration page
|
||||
|
||||
class DragBoxConfigPage < RBA::ConfigPage
|
||||
# A (modal) option page, also called a "focus page". This page is
|
||||
# registered like an editor options page. It is brought to front
|
||||
# when the user hits the "Tab" key during editing.
|
||||
# In this case, this page uses "setup" and "apply" callbacks to
|
||||
# set and fetch information. It also employs a handler named
|
||||
# "update_box" to communicate changes between the client (the
|
||||
# plugin) and the page.
|
||||
#
|
||||
# Attributes that the client needs to take care of are
|
||||
# "self.box" (the current box), "self.pfix" (the start point)
|
||||
# and "self.update_box".
|
||||
|
||||
class DragBoxFocusPage < RBA::EditorOptionsPage
|
||||
|
||||
# Creates a new page with title "Options" and at
|
||||
# position 1 (second from left)
|
||||
|
||||
attr_accessor :box
|
||||
attr_accessor :pfix
|
||||
attr_accessor :update_box
|
||||
|
||||
def initialize
|
||||
|
||||
super("Geometry", 2)
|
||||
|
||||
self.focus_page = true
|
||||
self.modal_page = true
|
||||
|
||||
@box = RBA::DBox::new
|
||||
@pfix = RBA::DPoint::new
|
||||
|
||||
layout = RBA::QGridLayout::new(self)
|
||||
layout.setColumnStretch(1, 1)
|
||||
|
||||
label = RBA::QLabel::new("Width", self)
|
||||
layout.addWidget(label, 0, 0, 1, 1)
|
||||
@le_width = RBA::QLineEdit::new(self)
|
||||
layout.addWidget(@le_width, 0, 1, 1, 1)
|
||||
|
||||
label = RBA::QLabel::new("Height", self)
|
||||
layout.addWidget(label, 1, 0, 1, 1)
|
||||
@le_height = RBA::QLineEdit::new(self)
|
||||
layout.addWidget(@le_height, 1, 1, 1, 1)
|
||||
|
||||
layout.setRowStretch(2, 1)
|
||||
|
||||
end
|
||||
|
||||
# Is called when the page needs to be set up.
|
||||
# We assume that the client has properly set up self.box
|
||||
def setup(dispatcher)
|
||||
@le_width.text = "%.12g" % @box.width
|
||||
@le_height.text = "%.12g" % @box.height
|
||||
end
|
||||
|
||||
# Apply is called when the dialog is accepted or the "Apply" button is pressed
|
||||
# Usually this method is intended to submit configuration parameter changes,
|
||||
# but we can use it for any other purpose as well.
|
||||
|
||||
# places the widget on a new section ("Drag Box")
|
||||
# and "Configure" page
|
||||
def apply(dispatcher)
|
||||
|
||||
# fetches the coordinates from the entry boxes
|
||||
# throws an exception in case of an error
|
||||
x = @le_width.text.to_f
|
||||
y = @le_height.text.to_f
|
||||
|
||||
# prepares a new box with the given dimensions
|
||||
# using the initial point ("pfix") and considering
|
||||
# the drag direction
|
||||
t = b = @pfix.y
|
||||
l = r = @pfix.x
|
||||
|
||||
if @box.bottom < t - 1e-10
|
||||
b = t - y
|
||||
else
|
||||
t = b + y
|
||||
end
|
||||
|
||||
if @box.left < l - 1e-10
|
||||
l = r - x
|
||||
else
|
||||
r = l + x
|
||||
end
|
||||
|
||||
# issue the event (call the handler) to inform the plugin of this change
|
||||
if @update_box
|
||||
@update_box.call(RBA::DBox::new(l, b, r, t))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# The widget placed into the configuration page
|
||||
|
||||
# A configuration page with a single entry box to change
|
||||
# the box color in RGB hex style.
|
||||
# Configuration pages appear in the Setup dialog and can
|
||||
# communicate only through configuration parameter updates.
|
||||
|
||||
class DragBoxConfigPage < RBA::ConfigPage
|
||||
|
||||
# Initializes the page. Places it on a new section ("Drag Box") and "Configure" page
|
||||
# and creates a single entry field.
|
||||
def initialize
|
||||
|
||||
super("Drag Box|Configure")
|
||||
|
||||
# Qt user interface setup
|
||||
layout = RBA::QHBoxLayout::new(self)
|
||||
label = RBA::QLabel::new("Color (hex, rrggbb)", self)
|
||||
layout.addWidget(label)
|
||||
|
|
@ -82,22 +197,26 @@ class DragBoxConfigPage < RBA::ConfigPage
|
|||
|
||||
end
|
||||
|
||||
# This method is called to request an update of the entry fields
|
||||
def setup(dispatcher)
|
||||
@line_edit.setText(dispatcher.get_config(CFG_COLOR))
|
||||
end
|
||||
|
||||
# This method is called to request a transfer of the edited values
|
||||
# to the configuration space.
|
||||
def apply(dispatcher)
|
||||
dispatcher.set_config(CFG_COLOR, @line_edit.text)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# The custom plugin implementation.
|
||||
|
||||
class DragBoxPlugin < RBA::Plugin
|
||||
|
||||
def initialize(view)
|
||||
super()
|
||||
@marker = nil
|
||||
@last_box = nil
|
||||
@last_marker = nil
|
||||
@box = nil
|
||||
@start_point = nil
|
||||
@view = view
|
||||
|
|
@ -105,14 +224,14 @@ class DragBoxPlugin < RBA::Plugin
|
|||
@width = 1
|
||||
end
|
||||
|
||||
# This method receives configuration callbacks
|
||||
def configure(name, value)
|
||||
# receives configuration callbacks
|
||||
if name == CFG_COLOR
|
||||
# configure marker color
|
||||
begin
|
||||
@color = value != "" ? value.to_i(16) : nil
|
||||
rescue
|
||||
self.color = nil
|
||||
@color = nil
|
||||
end
|
||||
self._configure_marker
|
||||
elsif name == CFG_WIDTH
|
||||
|
|
@ -126,57 +245,97 @@ class DragBoxPlugin < RBA::Plugin
|
|||
end
|
||||
end
|
||||
|
||||
# clears all markers
|
||||
def _clear_marker
|
||||
# clears all markers
|
||||
[ @marker, @last_box ].each { |m| m && m._destroy }
|
||||
[ @marker, @last_marker ].each { |marker| marker && marker._destroy }
|
||||
@marker = nil
|
||||
@last_box = nil
|
||||
@last_marker = nil
|
||||
end
|
||||
|
||||
# stops dragging the marker and copy to a static one
|
||||
def _finish
|
||||
if @last_marker
|
||||
@last_marker._destroy
|
||||
end
|
||||
@last_marker = @marker
|
||||
@marker = nil
|
||||
# reset to idle
|
||||
self.ungrab_mouse
|
||||
RBA::MainWindow.instance.message("Box finished: " + @box.to_s, 10000)
|
||||
end
|
||||
|
||||
# updates the marker with the current box
|
||||
def _update_marker
|
||||
# updates the marker with the current box
|
||||
if !@marker
|
||||
@marker = RBA::Marker::new(self.view)
|
||||
if ! @marker
|
||||
@marker = RBA::Marker::new(@view)
|
||||
self._configure_marker
|
||||
end
|
||||
@marker.set(@box)
|
||||
end
|
||||
|
||||
def freeze_marker
|
||||
# stop dragging the marker and copy to a static one
|
||||
if @last_box
|
||||
@last_box._destroy()
|
||||
end
|
||||
@last_box = @marker
|
||||
@marker = nil
|
||||
end
|
||||
|
||||
# changes the marker's appearance
|
||||
def _configure_marker
|
||||
# change the marker's appearance
|
||||
if @marker
|
||||
@marker.line_style = 2 # short-dashed
|
||||
@marker.vertex_size = 0 # no vertexes
|
||||
@marker.line_width = @width
|
||||
@marker.color = @color ? (@color | 0xff000000) : 0
|
||||
@marker.color = @color ? (@color | 0xff000000) : 0 # auto
|
||||
end
|
||||
end
|
||||
|
||||
# Updates the box with the given value and updates the marker.
|
||||
# This method is bound to the focus page handler when needed.
|
||||
def _update_box(box)
|
||||
@box = box
|
||||
self._update_marker
|
||||
end
|
||||
|
||||
# overloaded callback: the focus page is requested
|
||||
def focus_page_open(fp)
|
||||
|
||||
# stop unless dragging
|
||||
if !@marker
|
||||
return
|
||||
end
|
||||
|
||||
# configure the focus page and show it:
|
||||
# the page will call the handler of "update_box" to commit
|
||||
# changes to the box
|
||||
fp.box = @box
|
||||
fp.pfix = @start_point
|
||||
fp.update_box = lambda { |box| self._update_box(box) }
|
||||
ret = fp.show
|
||||
fp.update_box = nil
|
||||
if ret == 1
|
||||
# accepted: stop dragging now, we are done.
|
||||
self._finish
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
# overloaded callback:
|
||||
# plugin is activated - i.e. the mode is selected
|
||||
def activated
|
||||
# plugin is activated - i.e. the mode is selected
|
||||
RBA::MainWindow.instance.message("Click on point to start dragging a box", 10000)
|
||||
end
|
||||
|
||||
# overloaded callback:
|
||||
# plugin is deactivated - i.e. the mode is unselected
|
||||
def deactivated
|
||||
# plugin is deactivated - i.e. the mode is unselected
|
||||
self._clear_marker
|
||||
RBA::MainWindow.instance.message("", 0)
|
||||
end
|
||||
|
||||
# overloaded callback:
|
||||
# a mouse button was clicked
|
||||
|
||||
def mouse_click_event(p, buttons, prio)
|
||||
|
||||
if prio
|
||||
|
||||
# first-level event: start a new box or
|
||||
# stop dragging it and freeze the box
|
||||
if !@marker
|
||||
if ! @marker
|
||||
p = self.snap2(p)
|
||||
@box = RBA::DBox::new(p, p)
|
||||
@start_point = p
|
||||
|
|
@ -186,49 +345,55 @@ class DragBoxPlugin < RBA::Plugin
|
|||
RBA::MainWindow.instance.message("Drag the box and click again", 10000)
|
||||
else
|
||||
p = self.snap2(p, @start_point, true, self.ac_from_buttons(buttons))
|
||||
self.freeze_marker
|
||||
self.ungrab_mouse
|
||||
RBA::MainWindow.instance.message("Box finished: " + @box.to_s, 10000)
|
||||
self._update_box(RBA::DBox::new(@start_point, p))
|
||||
self._finish
|
||||
end
|
||||
# consume event
|
||||
|
||||
return true
|
||||
else
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
# overloaded callback:
|
||||
# the mouse was moved
|
||||
def mouse_moved_event(p, buttons, prio)
|
||||
|
||||
if prio
|
||||
# first-level event: if not dragging, provide a
|
||||
# mouse cursor for tracking. If dragging, update
|
||||
# the box and provide a mouse cursor.
|
||||
if !@marker
|
||||
self.clear_mouse_cursors
|
||||
p = self.snap2(p, true)
|
||||
p = self.snap2(p, :visualize => true)
|
||||
self.add_mouse_cursor(p)
|
||||
else
|
||||
self.clear_mouse_cursors
|
||||
p = self.snap2(p, @start_point, true, self.ac_from_buttons(buttons), true)
|
||||
p = self.snap2(p, @start_point, true, self.ac_from_buttons(buttons), :visualize => true)
|
||||
self.add_mouse_cursor(p)
|
||||
@box = RBA::DBox::new(@start_point, p)
|
||||
self._update_marker
|
||||
end
|
||||
end
|
||||
|
||||
# NOTE: we must not digest this event (i.e. return true)
|
||||
# to allow the mouse tracker to receive the events as well
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Implements a "plugin factory".
|
||||
# Purpose of this object is to create a plugin object
|
||||
# The purpose of this object is to create a plugin object
|
||||
# and corresponding UI objects.
|
||||
|
||||
class DragBoxPluginFactory < RBA::PluginFactory
|
||||
|
||||
def initialize
|
||||
super()
|
||||
super
|
||||
self.has_tool_entry = true
|
||||
# NOTE: it's a good practice to register configuration options
|
||||
self.add_option(CFG_WIDTH, "1")
|
||||
|
|
@ -236,23 +401,28 @@ class DragBoxPluginFactory < RBA::PluginFactory
|
|||
self.register(-1000, "drag_box", "Drag Box")
|
||||
end
|
||||
|
||||
# Called to create the configuration pages
|
||||
def create_config_pages
|
||||
self.add_config_page(DragBoxConfigPage::new)
|
||||
end
|
||||
|
||||
# Called to create the editor options pages
|
||||
def create_editor_options_pages
|
||||
self.add_editor_options_page(DragBoxEditorOptionsPage::new)
|
||||
self.add_editor_options_page(DragBoxFocusPage::new)
|
||||
end
|
||||
|
||||
# Creates the plugin
|
||||
def create_plugin(manager, root, view)
|
||||
return DragBoxPlugin::new(view)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# Create the singleton instance - as we register it,
|
||||
end
|
||||
|
||||
# Creates the singleton instance - as we register it,
|
||||
# it is not garbage collected
|
||||
DragBoxPluginFactory::new
|
||||
|
||||
end</text>
|
||||
end
|
||||
</text>
|
||||
</klayout-macro>
|
||||
|
|
|
|||
|
|
@ -8,15 +8,23 @@
|
|||
<shortcut></shortcut>
|
||||
<interpreter>python</interpreter>
|
||||
<text># Sample plugin
|
||||
#
|
||||
|
||||
# This plugin implements a box that can be drawn by
|
||||
# clicking at the first and then at the second point.
|
||||
# There is one box which is replacing the previous one.
|
||||
# Line color and line width of the box can be configured
|
||||
# by editor options (line width) or configuration pages
|
||||
# (color).
|
||||
|
||||
# (color). These settings are managed through configuration
|
||||
# options and their current state is persisted.
|
||||
#
|
||||
# The dimension of the box can be entered numerically
|
||||
# while dragging the box. This feature is implemented
|
||||
# through a modal "focus page", which opens when you
|
||||
# press the Tab key during editing and when the keyboard
|
||||
# focus is on the canvas.
|
||||
#
|
||||
# Register this macro as "autorun" to enable the plugin
|
||||
# on startup.
|
||||
|
||||
cfg_color = "drag-box-color"
|
||||
cfg_width = "drag-box-width"
|
||||
|
|
@ -24,11 +32,19 @@ cfg_width = "drag-box-width"
|
|||
# The widget placed into the editor options dock
|
||||
|
||||
class DragBoxEditorOptionsPage(pya.EditorOptionsPage):
|
||||
|
||||
"""
|
||||
An option page providing a single entry box for configuring the line width
|
||||
This page communicates via configuration options. One advantage of this
|
||||
approach is that the values are persisted
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Creates a new page with title "Options" and at
|
||||
# position 1 (second from left)
|
||||
"""
|
||||
Creates a new page with title "Options" and at position 1 (second from left)
|
||||
"""
|
||||
|
||||
super(DragBoxEditorOptionsPage, self).__init__("Options", 1)
|
||||
|
||||
layout2 = pya.QVBoxLayout(self)
|
||||
|
|
@ -43,25 +59,142 @@ class DragBoxEditorOptionsPage(pya.EditorOptionsPage):
|
|||
layout.addStretch(1)
|
||||
layout2.addStretch(1)
|
||||
|
||||
# connect the spin box value change with the "edited" slot
|
||||
# which will result in a call of "apply".
|
||||
self.spin_box.valueChanged = lambda x: self.edited()
|
||||
|
||||
def setup(self, dispatcher):
|
||||
|
||||
"""
|
||||
"setup" is called when the page needs to be populated with information -
|
||||
i.e. on first show.
|
||||
"""
|
||||
|
||||
try:
|
||||
self.spin_box.setValue(int(dispatcher.get_config(cfg_width)))
|
||||
except:
|
||||
self.spin_box.setValue(1)
|
||||
|
||||
def apply(self, dispatcher):
|
||||
|
||||
"""
|
||||
"apply" is called when the page is requested to submit the entered
|
||||
values to the plugin. Usually this should be done via configuration
|
||||
events.
|
||||
"""
|
||||
|
||||
dispatcher.set_config(cfg_width, str(self.spin_box.value))
|
||||
|
||||
# The modal dialog page that appears when "Tab" is pressed
|
||||
|
||||
class DragBoxFocusPage(pya.EditorOptionsPage):
|
||||
|
||||
"""
|
||||
A (modal) option page, also called a "focus page". This page is
|
||||
registered like an editor options page. It is brought to front
|
||||
when the user hits the "Tab" key during editing.
|
||||
In this case, this page uses "setup" and "apply" callbacks to
|
||||
set and fetch information. It also employs a handler named
|
||||
"update_box" to communicate changes between the client (the
|
||||
plugin) and the page.
|
||||
|
||||
Attributes that the client needs to take care of are
|
||||
"self.box" (the current box), "self.pfix" (the start point)
|
||||
and "self.update_box".
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
"""
|
||||
Creates a new page with title "Options" and at
|
||||
position 1 (second from left)
|
||||
"""
|
||||
|
||||
super(DragBoxFocusPage, self).__init__("Geometry", 2)
|
||||
|
||||
self.focus_page = True
|
||||
self.modal_page = True
|
||||
|
||||
self.box = pya.DBox()
|
||||
self.pfix = pya.DPoint()
|
||||
self.update_box = None
|
||||
|
||||
layout = pya.QGridLayout(self)
|
||||
layout.setColumnStretch(1, 1)
|
||||
|
||||
label = pya.QLabel("Width", self)
|
||||
layout.addWidget(label, 0, 0, 1, 1)
|
||||
self.le_width = pya.QLineEdit(self)
|
||||
layout.addWidget(self.le_width, 0, 1, 1, 1)
|
||||
|
||||
label = pya.QLabel("Height", self)
|
||||
layout.addWidget(label, 1, 0, 1, 1)
|
||||
self.le_height = pya.QLineEdit(self)
|
||||
layout.addWidget(self.le_height, 1, 1, 1, 1)
|
||||
|
||||
layout.setRowStretch(2, 1)
|
||||
|
||||
def setup(self, dispatcher):
|
||||
|
||||
"""
|
||||
Is called when the page needs to be set up.
|
||||
We assume that the client has properly set up self.box
|
||||
"""
|
||||
|
||||
self.le_width.text = "%.12g" % self.box.width()
|
||||
self.le_height.text = "%.12g" % self.box.height()
|
||||
|
||||
def apply(self, dispatcher):
|
||||
|
||||
"""
|
||||
Apply is called when the dialog is accepted or the "Apply" button is pressed
|
||||
Usually this method is intended to submit configuration parameter changes,
|
||||
but we can use it for any other purpose as well.
|
||||
"""
|
||||
|
||||
# fetches the coordinates from the entry boxes
|
||||
# throws an exception in case of an error
|
||||
x = float(self.le_width.text)
|
||||
y = float(self.le_height.text)
|
||||
|
||||
# prepares a new box with the given dimensions
|
||||
# using the initial point ("pfix") and considering
|
||||
# the drag direction
|
||||
t = b = self.pfix.y
|
||||
l = r = self.pfix.x
|
||||
|
||||
if self.box.bottom < t - 1e-10:
|
||||
b = t - y
|
||||
else:
|
||||
t = b + y
|
||||
|
||||
if self.box.left < l - 1e-10:
|
||||
l = r - x
|
||||
else:
|
||||
r = l + x
|
||||
|
||||
# issue the event (call the handler) to inform the plugin of this change
|
||||
if self.update_box is not None:
|
||||
self.update_box(pya.DBox(l, b, r, t))
|
||||
|
||||
# The widget placed into the configuration page
|
||||
|
||||
class DragBoxConfigPage(pya.ConfigPage):
|
||||
|
||||
"""
|
||||
A configuration page with a single entry box to change
|
||||
the box color in RGB hex style.
|
||||
Configuration pages appear in the Setup dialog and can
|
||||
communicate only through configuration parameter updates.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# places the widget on a new section ("Drag Box")
|
||||
# and "Configure" page
|
||||
"""
|
||||
Initializes the page. Places it on a new section ("Drag Box") and "Configure" page
|
||||
and creates a single entry field.
|
||||
"""
|
||||
|
||||
super(DragBoxConfigPage, self).__init__("Drag Box|Configure")
|
||||
|
||||
layout = pya.QHBoxLayout(self)
|
||||
|
|
@ -72,17 +205,28 @@ class DragBoxConfigPage(pya.ConfigPage):
|
|||
layout.addStretch(1)
|
||||
|
||||
def setup(self, dispatcher):
|
||||
"""
|
||||
This method is called to request an update of the entry fields
|
||||
"""
|
||||
self.line_edit.setText(dispatcher.get_config(cfg_color))
|
||||
|
||||
def apply(self, dispatcher):
|
||||
"""
|
||||
This method is called to request a transfer of the edited values
|
||||
to the configuration space.
|
||||
"""
|
||||
dispatcher.set_config(cfg_color, self.line_edit.text)
|
||||
|
||||
class DragBoxPlugin(pya.Plugin):
|
||||
|
||||
"""
|
||||
The custom plugin implementation.
|
||||
"""
|
||||
|
||||
def __init__(self, view):
|
||||
super(DragBoxPlugin, self).__init__()
|
||||
self.marker = None
|
||||
self.last_box = None
|
||||
self.last_marker = None
|
||||
self.box = None
|
||||
self.start_point = None
|
||||
self.view = view
|
||||
|
|
@ -90,8 +234,9 @@ class DragBoxPlugin(pya.Plugin):
|
|||
self.width = 1
|
||||
|
||||
def configure(self, name, value):
|
||||
# receives configuration callbacks
|
||||
needs_update = False
|
||||
"""
|
||||
This method receives configuration callbacks
|
||||
"""
|
||||
if name == cfg_color:
|
||||
# configure marker color
|
||||
try:
|
||||
|
|
@ -111,29 +256,40 @@ class DragBoxPlugin(pya.Plugin):
|
|||
self._configure_marker()
|
||||
|
||||
def _clear_marker(self):
|
||||
# clears all markers
|
||||
for marker in [ self.marker, self.last_box ]:
|
||||
"""
|
||||
clears all markers
|
||||
"""
|
||||
for marker in [ self.marker, self.last_marker ]:
|
||||
if marker is not None:
|
||||
marker._destroy()
|
||||
self.marker = None
|
||||
self.last_box = None
|
||||
self.last_marker = None
|
||||
|
||||
def _finish(self):
|
||||
"""
|
||||
stops dragging the marker and copy to a static one
|
||||
"""
|
||||
if self.last_marker is not None:
|
||||
self.last_marker._destroy()
|
||||
self.last_marker = self.marker
|
||||
self.marker = None
|
||||
# reset to idle
|
||||
self.ungrab_mouse()
|
||||
pya.MainWindow.instance().message("Box finished: " + str(self.box), 10000)
|
||||
|
||||
def _update_marker(self):
|
||||
# updates the marker with the current box
|
||||
"""
|
||||
updates the marker with the current box
|
||||
"""
|
||||
if self.marker is None:
|
||||
self.marker = pya.Marker(self.view)
|
||||
self._configure_marker()
|
||||
self.marker.set(self.box)
|
||||
|
||||
def freeze_marker(self):
|
||||
# stop dragging the marker and copy to a static one
|
||||
if self.last_box is not None:
|
||||
self.last_box._destroy()
|
||||
self.last_box = self.marker
|
||||
self.marker = None
|
||||
|
||||
def _configure_marker(self):
|
||||
# change the marker's appearance
|
||||
"""
|
||||
changes the marker's appearance
|
||||
"""
|
||||
if self.marker is not None:
|
||||
self.marker.line_style = 2 # short-dashed
|
||||
self.marker.vertex_size = 0 # no vertexes
|
||||
|
|
@ -142,17 +298,64 @@ class DragBoxPlugin(pya.Plugin):
|
|||
self.marker.color = self.color | 0xff000000
|
||||
else:
|
||||
self.marker.color = 0 # auto
|
||||
|
||||
def _update_box(self, box):
|
||||
"""
|
||||
Updates the box with the given value and updates the marker.
|
||||
This method is bound to the focus page handler when needed.
|
||||
"""
|
||||
self.box = box
|
||||
self._update_marker()
|
||||
|
||||
def focus_page_open(self, fp):
|
||||
|
||||
"""
|
||||
overloaded callback: the focus page is requested
|
||||
"""
|
||||
|
||||
# stop unless dragging
|
||||
if self.marker is None:
|
||||
return
|
||||
|
||||
# configure the focus page and show it:
|
||||
# the page will call the handler of "update_box" to commit
|
||||
# changes to the box
|
||||
fp.box = self.box
|
||||
fp.pfix = self.start_point
|
||||
fp.update_box = self._update_box
|
||||
ret = fp.show()
|
||||
fp.update_box = None
|
||||
if ret == 1:
|
||||
# accepted: stop dragging now, we are done.
|
||||
self._finish()
|
||||
return ret
|
||||
|
||||
def activated(self):
|
||||
# plugin is activated - i.e. the mode is selected
|
||||
|
||||
"""
|
||||
overloaded callback:
|
||||
plugin is activated - i.e. the mode is selected
|
||||
"""
|
||||
|
||||
pya.MainWindow.instance().message("Click on point to start dragging a box", 10000)
|
||||
|
||||
def deactivated(self):
|
||||
# plugin is deactivated - i.e. the mode is unselected
|
||||
|
||||
"""
|
||||
overloaded callback:
|
||||
plugin is deactivated - i.e. the mode is unselected
|
||||
"""
|
||||
|
||||
self._clear_marker()
|
||||
pya.MainWindow.instance().message("", 0)
|
||||
|
||||
def mouse_click_event(self, p, buttons, prio):
|
||||
|
||||
"""
|
||||
overloaded callback:
|
||||
a mouse button was clicked
|
||||
"""
|
||||
|
||||
if prio:
|
||||
# first-level event: start a new box or
|
||||
# stop dragging it and freeze the box
|
||||
|
|
@ -166,13 +369,18 @@ class DragBoxPlugin(pya.Plugin):
|
|||
pya.MainWindow.instance().message("Drag the box and click again", 10000)
|
||||
else:
|
||||
p = self.snap2(p, self.start_point, True, self.ac_from_buttons(buttons))
|
||||
self.freeze_marker()
|
||||
self.ungrab_mouse()
|
||||
pya.MainWindow.instance().message("Box finished: " + str(self.box), 10000)
|
||||
self._update_box(pya.DBox(self.start_point, p))
|
||||
self._finish()
|
||||
return True
|
||||
return False
|
||||
|
||||
def mouse_moved_event(self, p, buttons, prio):
|
||||
|
||||
"""
|
||||
overloaded callback:
|
||||
the mouse was moved
|
||||
"""
|
||||
|
||||
if prio:
|
||||
# first-level event: if not dragging, provide a
|
||||
# mouse cursor for tracking. If dragging, update
|
||||
|
|
@ -191,13 +399,14 @@ class DragBoxPlugin(pya.Plugin):
|
|||
# to allow the mouse tracker to receive the events as well
|
||||
return False
|
||||
|
||||
|
||||
# Implements a "plugin factory".
|
||||
# Purpose of this object is to create a plugin object
|
||||
# and corresponding UI objects.
|
||||
|
||||
class DragBoxPluginFactory(pya.PluginFactory):
|
||||
|
||||
"""
|
||||
Implements a "plugin factory".
|
||||
The purpose of this object is to create a plugin object
|
||||
and corresponding UI objects.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(DragBoxPluginFactory, self).__init__()
|
||||
self.has_tool_entry = True
|
||||
|
|
@ -207,15 +416,25 @@ class DragBoxPluginFactory(pya.PluginFactory):
|
|||
self.register(-1000, "drag_box", "Drag Box")
|
||||
|
||||
def create_config_pages(self):
|
||||
"""
|
||||
Called to create the configuration pages
|
||||
"""
|
||||
self.add_config_page(DragBoxConfigPage())
|
||||
|
||||
def create_editor_options_pages(self):
|
||||
"""
|
||||
Called to create the editor options pages
|
||||
"""
|
||||
self.add_editor_options_page(DragBoxEditorOptionsPage())
|
||||
self.add_editor_options_page(DragBoxFocusPage())
|
||||
|
||||
def create_plugin(self, manager, root, view):
|
||||
"""
|
||||
Creates the plugin
|
||||
"""
|
||||
return DragBoxPlugin(view)
|
||||
|
||||
# Create the singleton instance - as we register it,
|
||||
# Creates the singleton instance - as we register it,
|
||||
# it is not garbage collected
|
||||
DragBoxPluginFactory()
|
||||
</text>
|
||||
|
|
|
|||
Loading…
Reference in New Issue