| Issue 246: | Extend MTInnerWindow to add aspect ratio controls | |
| 3 people starred this issue and may be notified of changes. | Back to list |
Enhance the MTInnerWindow with controls for changing the aspect ratio of
the window just like any OS window works.
My first attempt is shown below. It works except for when rotated and
altering the size from any aspect control other than that at the top right
of the window.
# PYMT Plugin integration
IS_PYMT_PLUGIN = True
PLUGIN_TITLE = 'Napier Browser'
PLUGIN_AUTHOR = 'Jay Bradley'
PLUGIN_DESCRIPTION = 'Browse through file and search web resources'
from pymt import *
import os
import random
from OpenGL.GL import *
current_dir = os.path.dirname(__file__)
class MTNapierInnerWindow(MTInnerWindow):
def __init__(self, **kwargs):
print "MTNapierInnerWindow constructed"
kwargs.setdefault('scale_min', 0.5)
kwargs.setdefault('scale_max', 2)
self.height_max = 600
self.height_min = 100
self.width_max = 600
self.width_min = 200
self.grow_delta = Vector(0, 0)
self.aspect_controls_touches = {}
MTInnerWindow.__init__(self, **kwargs)
self.add_hold_aspect_ratio_controls()
def fullscreen(self, *largs, **kwargs):
self.hide_hold_aspect_ratio_controls()
root_win = self.parent.get_parent_window()
parent_widget = self.parent
# save state for restore
self.old_children = parent_widget.children
self.old_size = self.size
# set new children
parent_widget.children = SafeList()
rotation_to_nearest_90 = int(round(self.rotation / 90, 0)) * 90
self.orientation_widget = MTScatterWidget(size = root_win.size,
rotation = rotation_to_nearest_90) # round rotation to nearest compass point
if(rotation_to_nearest_90 == 0 or rotation_to_nearest_90 == 360):
self.size = self.orientation_widget.size
self.container.size = self.size
elif(rotation_to_nearest_90 == 90):
self.orientation_widget.pos = (self.orientation_widget.pos[0] +
self.orientation_widget.width, self.orientation_widget.pos[1])
self.orientation_widget.size = (self.orientation_widget.size[1],
self.orientation_widget.size[0]) # swap height and width because it's on
its side
self.size = self.orientation_widget.size
self.container.size = self.size
elif(rotation_to_nearest_90 == 180):
self.orientation_widget.pos = (self.orientation_widget.pos[0] +
self.orientation_widget.width, self.orientation_widget.pos[1] +
self.orientation_widget.height)
self.size = self.orientation_widget.size
self.container.size = self.size
elif(rotation_to_nearest_90 == 270):
self.orientation_widget.pos = (self.orientation_widget.pos[0],
self.orientation_widget.pos[1] + self.orientation_widget.height)
self.orientation_widget.size = (self.orientation_widget.size[1],
self.orientation_widget.size[0]) # swap height and width because it's on
its side
self.size = self.orientation_widget.size
self.container.size = self.size
parent_widget.add_widget(self.orientation_widget)
self.orientation_widget.add_widget(self.container)
btn_unfullscreen = MTButton(pos=(self.orientation_widget.width-50,
self.orientation_widget.height-50), size=(50,50), label='Back')
btn_unfullscreen.push_handlers(on_release=self.unfullscreen)
self.orientation_widget.add_widget(btn_unfullscreen)
def unfullscreen(self, *largs, **kwargs):
# restore old widget
parent_widget = self.parent
parent_widget.children = self.old_children
# reset container parent
self.container.parent = self
# set old size
self.size = self.old_size
self.container.size = self.size
self.show_hold_aspect_ratio_controls()
def add_hold_aspect_ratio_controls(self):
scaled_border = self.get_scaled_border()
self.aspect_controls = MTWidget()
self.add_widget(self.aspect_controls) # not sure if this is needed.
Works without it.
self.aspect_control_bottom_left = MTButton(pos=(-scaled_border,
-scaled_border), size = (scaled_border, scaled_border),
cls="aspect_ratio_controls")
self.aspect_controls.add_widget(self.aspect_control_bottom_left)
self.aspect_control_top_left = MTButton(pos=(-scaled_border,
self.height), size = (scaled_border, scaled_border),
cls="aspect_ratio_controls")
self.aspect_controls.add_widget(self.aspect_control_top_left)
self.aspect_control_bottom_right = MTButton(pos=(self.width,
-scaled_border), size = (scaled_border, scaled_border),
cls="aspect_ratio_controls")
self.aspect_controls.add_widget(self.aspect_control_bottom_right)
self.aspect_control_top_right = MTButton(pos=(self.width, self.height),
size = (scaled_border, scaled_border), cls="aspect_ratio_controls")
self.aspect_controls.add_widget(self.aspect_control_top_right)
def hide_hold_aspect_ratio_controls(self):
self.aspect_controls.visible = False
def show_hold_aspect_ratio_controls(self):
self.aspect_controls.visible = True
def update_aspect_controls(self):
scaled_border = self.get_scaled_border()
scale_of_aspect_controls = 0.8
size_of_aspect_controls = scaled_border * scale_of_aspect_controls
self.aspect_control_bottom_left.pos = (-scaled_border *
scale_of_aspect_controls, -scaled_border * scale_of_aspect_controls)
self.aspect_control_bottom_left.size = (size_of_aspect_controls,
size_of_aspect_controls)
self.aspect_control_top_left.pos = (-scaled_border *
scale_of_aspect_controls, self.height)
self.aspect_control_top_left.size = (size_of_aspect_controls,
size_of_aspect_controls)
self.aspect_control_bottom_right.pos = (self.width, -scaled_border *
scale_of_aspect_controls)
self.aspect_control_bottom_right.size = (size_of_aspect_controls,
size_of_aspect_controls)
self.aspect_control_top_right.pos = (self.width, self.height)
self.aspect_control_top_right.size = (size_of_aspect_controls,
size_of_aspect_controls)
def on_touch_down(self, touch):
if(len(self.aspect_controls_touches.keys()) == 0): # only one touch
allowed at a time on the aspect ratio controls
local_touch = self.to_local(touch.x, touch.y)
if(self.aspect_control_bottom_left.collide_point(local_touch[0],
local_touch[1])):
#print "MTNapierInnerWindow touch down over bottom left aspect control"
self.aspect_controls_touches[touch.id] = ["bottom", "left"]
elif(self.aspect_control_top_left.collide_point(local_touch[0],
local_touch[1])):
#print "MTNapierInnerWindow touch down over top left aspect control"
self.aspect_controls_touches[touch.id] = ["top", "left"]
elif(self.aspect_control_bottom_right.collide_point(local_touch[0],
local_touch[1])):
#print "MTNapierInnerWindow touch down over bottom right aspect
control"
self.aspect_controls_touches[touch.id] = ["bottom", "right"]
elif(self.aspect_control_top_right.collide_point(local_touch[0],
local_touch[1])):
#print "MTNapierInnerWindow touch down over top right aspect control"
self.aspect_controls_touches[touch.id] = ["top", "right"]
#else:
#'print "MTNapierInnerWindow touch down NOT over aspect controls"
MTInnerWindow.on_touch_down(self, touch)
def on_touch_up(self, touch):
# if touch in self.aspect_controls_touches then remove it
if(touch.id in self.aspect_controls_touches.keys()):
del self.aspect_controls_touches[touch.id]
MTInnerWindow.on_touch_up(self, touch)
def apply_angle_scale_trans(self, angle, scale, trans, point=Vector(0, 0)):
if(len(self.aspect_controls_touches.keys()) >= 1 and len(self.touches)
== 1): # change size rather than scale
grow_delta = Vector(trans.x, trans.y)
grow_delta = grow_delta.rotate(360.0 - self.rotation)
aspect_control_location = self.aspect_controls_touches.items()[0][1]
# handle switch in direction of growth
# left
if("left" in aspect_control_location):
grow_delta[0] *= -1.0
# bottom
if("bottom" in aspect_control_location):
grow_delta[1] *= -1.0
# change the size
self.width += grow_delta[0]
self.height += grow_delta[1]
# offset the window
trans.x = 0
trans.y = 0
# left
if("left" in aspect_control_location):
trans.x = -grow_delta[0]
# bottom
if("bottom" in aspect_control_location):
trans.y = -grow_delta[1]
# check that the widget isn't too small or too large
if(self.height <= self.height_min):
self.height = self.height_min
elif(self.height >= self.height_max):
self.height = self.height_max
if(self.width <= self.width_min):
self.width = self.width_min
elif(self.width >= self.width_max):
self.width = self.width_max
# resize the widget's container too
self.container.height = self.height
self.container.width = self.width
#invalidate cached values for parent transform calucaltion
self.__to_local = (-9999, 9999)
self.__to_parent = (-9999, 9999)
self.dispatch_event('on_transform', angle, scale, trans, point)
scale = 0
rotate = 0
#else:
# apply the changes as normal if not changing the aspect ratio
MTScatterWidget.apply_angle_scale_trans(self, angle, scale, trans, point)
def draw(self):
self.update_aspect_controls()
MTInnerWindow.draw(self)
self.aspect_controls.dispatch_event('on_draw')
Aug 15, 2010
Project Member
#1
txprog
Labels:
Type-Enhancement
Aug 19, 2010
(No comment was entered for this change.)
Labels:
Component-Widgets
|