283 lines
No EOL
7 KiB
Text
283 lines
No EOL
7 KiB
Text
#
|
|
# $Id: button.icn,v 1.7 2006-07-09 23:43:07 rparlett Exp $
|
|
#
|
|
# This file is in the public domain.
|
|
#
|
|
# Author: Robert Parlett (parlett@dial.pipex.com)
|
|
#
|
|
|
|
package gui
|
|
link graphics
|
|
|
|
$include "guih.icn"
|
|
|
|
|
|
#
|
|
# This is the parent class of the button classes, including
|
|
# checkboxes.
|
|
#
|
|
# A {Button} produces a BUTTON_PRESS_EVENT when the button is
|
|
# depressed, and code BUTTON_RELEASE_EVENT when it is released,
|
|
# as well as an ACTION_EVENT.
|
|
#
|
|
# By default, when a button holds the keyboard focus a dashed
|
|
# line appears just within the button. Then, when return is
|
|
# pressed an ACTION_EVENT is generated. The method
|
|
# {Dialog.set_initial_focus()} can be used to have the button
|
|
# have the focus when the dialog is first displayed.
|
|
#
|
|
# Buttons also repeatedly produce a BUTTON_HELD_EVENT whilst they
|
|
# are held down, rather like a repeating keyboard press. The
|
|
# delay between the initial repeat event and subsequent repeat
|
|
# events is set in the parent dialog (see above).
|
|
#
|
|
class Button : Toggle : Component(
|
|
is_down, #
|
|
is_held, #
|
|
is_checked_flag, #
|
|
label,
|
|
img_up, #
|
|
img_down, #
|
|
img_w, #
|
|
img_h, #
|
|
parent_check_box_group, #
|
|
parent_button_group, #
|
|
repeat_delay,
|
|
no_keyboard_flag, #
|
|
toggles_flag
|
|
)
|
|
|
|
method set_parent_button_group(x)
|
|
return self.parent_button_group := x
|
|
end
|
|
|
|
#
|
|
# Invoking this method disables the keyboard control over the
|
|
# button described above. No dashed line will ever appear in
|
|
# the button display and return will have no effect on the
|
|
# button even if it has the focus.
|
|
#
|
|
method set_no_keyboard()
|
|
self.no_keyboard_flag := 1
|
|
self.accepts_focus_flag := &null
|
|
end
|
|
|
|
#
|
|
# Clear the no keyboard behaviour (the default)
|
|
#
|
|
method clear_no_keyboard()
|
|
self.no_keyboard_flag := &null
|
|
self.accepts_focus_flag := 1
|
|
end
|
|
|
|
method tick()
|
|
if dispatcher.curr_time_of_day() > self.repeat_delay then
|
|
fire(BUTTON_HELD_EVENT)
|
|
end
|
|
|
|
method go_down()
|
|
self.is_down := 1
|
|
set_ticker(self.parent_dialog.repeat_rate)
|
|
end
|
|
|
|
method go_up()
|
|
self.is_down := &null
|
|
stop_ticker()
|
|
end
|
|
|
|
method handle_press(e)
|
|
local b
|
|
if self.in_region() then {
|
|
go_down()
|
|
self.repeat_delay := dispatcher.curr_time_of_day() + self.parent_dialog.repeat_delay
|
|
self.is_held := 1
|
|
every b := !(\self.parent_button_group).buttons do {
|
|
if b.is_unhidden() then {
|
|
b.is_held := 1
|
|
b.repeat_delay := self.repeat_delay
|
|
}
|
|
}
|
|
self.invalidate()
|
|
fire(BUTTON_PRESS_EVENT, e)
|
|
}
|
|
end
|
|
|
|
method handle_drag(e)
|
|
if \self.is_held then {
|
|
#
|
|
# Button held down; toggle on/off as it goes over the button
|
|
#
|
|
if self.in_region() then {
|
|
if /self.is_down then {
|
|
go_down()
|
|
invalidate()
|
|
}
|
|
} else {
|
|
if \self.is_down then {
|
|
go_up()
|
|
invalidate()
|
|
}
|
|
}
|
|
}
|
|
end
|
|
|
|
method handle_release(e)
|
|
if \self.is_held then {
|
|
self.is_held := &null
|
|
if \self.is_down then {
|
|
go_up()
|
|
fire(BUTTON_RELEASE_EVENT, e)
|
|
on_action(e)
|
|
}
|
|
}
|
|
end
|
|
|
|
method on_action(e)
|
|
if \self.toggles_flag then {
|
|
if \self.parent_check_box_group then
|
|
self.parent_check_box_group.set_which_one(self)
|
|
else
|
|
self.toggle_is_checked()
|
|
}
|
|
self.invalidate()
|
|
fire(ACTION_EVENT, e)
|
|
end
|
|
|
|
method handle_accel(e)
|
|
self.Component.handle_accel(e)
|
|
on_action(e)
|
|
end
|
|
|
|
method handle_default(e)
|
|
if \self.has_focus then {
|
|
if /self.no_keyboard_flag & e == ("\r" | "\l" | " ") then {
|
|
on_action(e)
|
|
}
|
|
}
|
|
end
|
|
|
|
method handle_event(e)
|
|
if e === (&lpress | &rpress | &mpress) then {
|
|
handle_press(e)
|
|
} else if e === (&ldrag | &rdrag | &mdrag) then {
|
|
handle_drag(e)
|
|
} else if e === (&lrelease | &rrelease | &mrelease) then {
|
|
handle_release(e)
|
|
} else
|
|
handle_default(e)
|
|
end
|
|
|
|
#
|
|
# Set the up/down images (if any) to the strings provided,
|
|
# which should be in Icon image format.
|
|
# The two images must have the same dimensions.
|
|
# @param x The up image
|
|
# @param y The down image
|
|
#
|
|
method set_imgs(x, y)
|
|
self.img_up := x
|
|
self.img_w := img_width(x) = img_width(y) | fatal("Image widths differ")
|
|
self.img_h := img_height(x) = img_height(y) | fatal("Image heights differ")
|
|
|
|
self.img_down := y
|
|
|
|
return
|
|
end
|
|
|
|
#
|
|
# Set the image (if any) to the given string, which should be in Icon image
|
|
# format.
|
|
# @param x The image
|
|
#
|
|
method set_img(x)
|
|
self.img_up := self.img_down := x
|
|
self.img_w := img_width(x)
|
|
self.img_h := img_height(x)
|
|
return x
|
|
end
|
|
|
|
#
|
|
# Toggle the checked status of the button. This method, and
|
|
# the following two methods, may be
|
|
# inappropriate for non-toggle styles of button.
|
|
#
|
|
method toggle_is_checked()
|
|
self.Toggle.toggle_is_checked()
|
|
self.invalidate()
|
|
end
|
|
|
|
#
|
|
# Set the status to checked.
|
|
#
|
|
method set_is_checked()
|
|
self.Toggle.set_is_checked()
|
|
self.invalidate()
|
|
end
|
|
|
|
#
|
|
# Set the status to unchecked.
|
|
#
|
|
method clear_is_checked()
|
|
self.Toggle.clear_is_checked()
|
|
self.invalidate()
|
|
end
|
|
|
|
#
|
|
# Set the button so that when it is pressed, it toggles
|
|
# between two states, as indicated by the is_checked
|
|
# flag.
|
|
#
|
|
# Instances of Checkbox have this flag on by default, but
|
|
# TextButton and IconButton do not. When the flag is on,
|
|
# the latter classes indicate their checked status by
|
|
# showing the button as being "down".
|
|
#
|
|
method set_toggles()
|
|
self.toggles_flag := 1
|
|
self.invalidate()
|
|
end
|
|
|
|
#
|
|
# Clear the toggles flag.
|
|
#
|
|
method clear_toggles()
|
|
self.toggles_flag := &null
|
|
self.invalidate()
|
|
end
|
|
|
|
#
|
|
# Set the label of the button, if any.
|
|
# @param x The label
|
|
#
|
|
method set_label(x)
|
|
self.label := x
|
|
self.invalidate()
|
|
return x
|
|
end
|
|
|
|
method set_one(attr, val)
|
|
case attr of {
|
|
"label" : set_label(string_val(attr, val))
|
|
"is_checked" :
|
|
if test_flag(attr, val) then
|
|
set_is_checked()
|
|
else
|
|
clear_is_checked()
|
|
"toggles" :
|
|
if test_flag(attr, val) then
|
|
set_toggles()
|
|
else
|
|
clear_toggles()
|
|
"no_keyboard" :
|
|
if test_flag(attr, val) then
|
|
set_no_keyboard()
|
|
else
|
|
clear_no_keyboard()
|
|
default: self.Component.set_one(attr, val)
|
|
}
|
|
end
|
|
|
|
initially()
|
|
self.Component.initially()
|
|
self.accepts_focus_flag := 1
|
|
end |