Wednesday, June 27, 2007

Peter Batty's thoughts on GE's spatial offerings on Oracle

For a former-insider's point of view on General Electric's announcement to create new GIS applications on the Oracle stack, see Peter Batty 's Thoughts on GE's next generation system based on Oracle - part 1.

I plan to write some more about this myself in the coming weeks, particularly as it relates to a recent demo I saw of the system running on Oracle.

Friday, June 22, 2007

progress counters and dialogs

I recently had a colleague ask me how to pop up a progress bar dialog to indicate to a user the percentage complete of a process. I did not know how to answer that at first... Smallworld has historically not used progress bar dialogs as much as some users would expect. So I will present two options for showing progress status.

Text-based process

If you have some kind of text based process use progress_counter...


_block
_local some_collection << rope.new(20)

# create a progress_counter class that reports every 5
# increments. Because we know some_collection.size we can also
# estimate completion time
_local pc << progress_counter.new_on_count(5,some_collection.size)

_for idx,an_el _over some_collection.fast_keys_and_elements()
_loop
# the write() and sleep() statements are here to make a simple
# example...
write(an_el)
_thisthread.sleep(1000)

# ... but the :next() method is important to let the
# progress_counter (aka PC) know that you have completed one
# iteration of the loop.
pc.next()
_endloop
_endblock
$
unset
unset
unset
unset
unset
Done 5 (15 left) time taken 5 seconds 297 milliseconds (ETC. 15 seconds 891 milliseconds ) average rate 0.9439305267
unset
unset
unset
unset
unset
Done 10 (10 left) time taken 10 seconds 625 milliseconds (ETC. 10 seconds 625 milliseconds ) average rate 0.9411844826
unset
unset
unset
unset
unset
Done 15 (5 left) time taken 15 seconds 812 milliseconds (ETC. 5 seconds 270 milliseconds ) average rate 0.9487724325
unset
unset
unset
unset
unset
Done 20 (0 left) time taken 21 seconds 15 milliseconds (ETC. 0 milliseconds ) average rate 0.9562876356



... you can also ask the progress_counter to report at a given time interval...


_block
_local some_collection << rope.new(20)

# create a progress_counter class that reports every 2
# seconds. Because we know some_collection.size we can also
# estimate completion time
_local pc << progress_counter.new_on_time(3,some_collection.size)

_for idx,an_el _over some_collection.fast_keys_and_elements()
_loop
# the write() and sleep() statements are here to make a simple
# example...
write(an_el)
_thisthread.sleep(1000)

# ... but the :next() method is important to let the
# progress_counter (aka PC) know that you have completed one
# iteration of the loop.
pc.next()
_endloop
_endblock
$
unset
unset
unset
Done 3 (17 left) time taken 3 seconds 125 milliseconds (ETC. 17 seconds 708 milliseconds ) average rate 0.9600000000
unset
unset
unset
Done 6 (14 left) time taken 6 seconds 250 milliseconds (ETC. 14 seconds 583 milliseconds ) average rate 0.9600000000
unset
unset
unset
Done 9 (11 left) time taken 9 seconds 359 milliseconds (ETC. 11 seconds 439 milliseconds ) average rate 0.9616468318
unset
unset
unset
Done 12 (8 left) time taken 12 seconds 453 milliseconds (ETC. 8 seconds 291 milliseconds ) average rate 0.9648530373
unset
unset
unset
Done 15 (5 left) time taken 15 seconds 578 milliseconds (ETC. 5 seconds 199 milliseconds ) average rate 0.9616468318
unset
unset
unset
Done 18 (2 left) time taken 18 seconds 703 milliseconds (ETC. 2 seconds 81 milliseconds ) average rate 0.9612351238
unset
unset
Done 20 (0 left) time taken 20 seconds 765 milliseconds (ETC. 0 milliseconds ) average rate 0.9612351238



If you want to use a more user-friendly indicator, use the progress_indicator_dialog. It is loaded into the core 4.1 image and you can find details about it in the header of product/modules/sw_core/progress_manager/source/progress_indicator_dialog.magik


_block
_local q << progress_indicator_dialog.new ( "Generating" )
q.interrupt_handler << handler.new ( _unset, _unset )
q.info_string << "The current series will contain approx 10 frames."
q.bar_label << "Generating frames..."
q.image << { :help, _unset }
q.activate ()

q.max_count << 10

_for n _over range(1,10,1)
_loop
_thisthread.sleep(1000)

q.progress_changed(n)
_endloop
_endblock
$


And there you have it... easy ways to let your users know the progress of a process.