You can subscribe to this list here.
| 2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(39) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(7) |
Jun
(31) |
Jul
(12) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
|
Nov
|
Dec
|
|
From: <fu...@us...> - 2003-12-15 20:11:58
|
Update of /cvsroot/neelix/neelix/model
In directory sc8-pr-cvs1:/tmp/cvs-serv13260/model
Modified Files:
model.rb
Log Message:
model.rb got a major overhaul. Took out all the commit/rollback stuff
(artifacts of an old paradigm), and tied the accessors directly to the db.
Added a nifty ObservableArray with many thanks to bartsman on #ruby-lang and a
few posts on comp.lang.ruby
The recipe name is complete in all its MVP glory. When you change the name of
the recipe in the form on the right, the variable is updated. Recipe then
notifies its observers (i.e. the FXTreeItem corresponding to the recipe) that
it has changed, and then the tree item updates with the new value.
Index: model.rb
===================================================================
RCS file: /cvsroot/neelix/neelix/model/model.rb,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** model.rb 14 Dec 2003 04:54:05 -0000 1.3
--- model.rb 15 Dec 2003 20:11:54 -0000 1.4
***************
*** 3,7 ****
require 'dbi'
require 'singleton'
! require 'observer'
class Food
--- 3,43 ----
require 'dbi'
require 'singleton'
! module Observable
! def add_observer(&callback)
! @observers ||= []
! @observers << callback
! end
!
! def delete_observer( &callback )
! @observers ||= []
! @observers.delete(callback)
! end
!
! protected
! def notify_observers
! @observers ||= []
! @observers.each { |o| o.call }
! end
! end
! class ObservableArray < Array
! include Observable
!
! class << self
! def wrap_method(*meths)
! meths.each do |meth|
! alias_method "__old_#{meth}", meth
! define_method(meth) do |*a|
! r = send("__old_#{meth}", *a);
! notify_observers
! r = ObservableArray.new(r) if Array === r
! return r
! end
! end
! end
! end
!
! wrap_method :<<, :[]=, :clear, :collect!, :compact!, :delete, :delete_at, :delete_if, :flatten!, :map!, :pop, :push, :reject!, :replace, :reverse!, :shift, :slice!, :sort!, :uniq!, :unshift
! wrap_method :assoc, :collect, :compact, :concat, :flatten, :rassoc, :reverse, :slice, :sort, :uniq
! end
class Food
***************
*** 9,13 ****
attr_reader :id
! attr_accessor :name, :measures
def initialize(dbh,food_id)
--- 45,49 ----
attr_reader :id
! attr_accessor :measures
def initialize(dbh,food_id)
***************
*** 17,58 ****
@dbh = dbh
@id = food_id
- rollback
- end
! def commit
! @dbh.do("update food set name=? where food_id=?",@name,@id)
! @dbh.commit
!
! # which measures were previously in the DB?
! @old_measures = Array.new
@dbh.select_all("select measure_id from food_measures where food_id=?",@id).each do |row|
! @old_measures << $replicator.get('measure', row['measure_id'])
end
! # add any new ones to the DB
! (@measures - @old_measures).each do |measure|
! @dbh.do("insert into food_measures (food_id,measure_id) values (?,?)",@id,measure.id)
! @dbh.commit
! end
! # remove any no longer used from the DB
! (@old_measures - @measures).each do |measure|
! @dbh.do("delete from food_measures where food_id=? and measure_id=?",@id,measure.id)
! @dbh.commit
! end
! changed
end
!
! def rollback
! @measures = Array.new
! @dbh.select_all("select measure_id from food_measures where food_id=?",@id).each do |row|
! @measures << $replicator.get('measure', row['measure_id'])
! end
! @name = @dbh.select_one("select name from food where food_id=?",@id)['name']
! changed
end
-
def to_s
! @name
end
end
--- 53,89 ----
@dbh = dbh
@id = food_id
! @measures = ObservableArray.new
@dbh.select_all("select measure_id from food_measures where food_id=?",@id).each do |row|
! @measures << $replicator.get('measure', row['measure_id'])
end
+ @measures.add_observer {
+ # which measures were previously in the DB?
+ old_measures = Array.new
+ @dbh.select_all("select measure_id from food_measures where food_id=?",@id).each do |row|
+ old_measures << $replicator.get('measure', row['measure_id'])
+ end
! # add any new ones to the DB
! (@measures - old_measures).each do |measure|
! @dbh.do("insert into food_measures (food_id,measure_id) values (?,?)",@id,measure.id)
! end
! # remove any no longer used from the DB
! (old_measures - @measures).each do |measure|
! @dbh.do("delete from food_measures where food_id=? and measure_id=?",@id,measure.id)
! end
! }
end
! def name
! @dbh.select_one("select name from food where food_id=?",@id)['name']
! end
! def name=(n)
! @dbh.do("update food set name=? where food_id=?",n,@id)
! notify_observers
! n
end
def to_s
! name
end
end
***************
*** 62,66 ****
attr_reader :id
- attr_accessor :name
def initialize(dbh,measure_id)
--- 93,96 ----
***************
*** 70,90 ****
@dbh = dbh
@id = measure_id
- rollback
end
- def commit
- @dbh.do("update measure set name=? where measure_id=?",@name,@id)
- @dbh.commit
- changed
- end
! def rollback
! # revert to DB state
! @name = @dbh.select_one("select name from measure where measure_id=?",@id)['name']
! changed
end
def to_s
! @name
end
end
--- 100,117 ----
@dbh = dbh
@id = measure_id
end
! def name
! @dbh.select_one("select name from measure where measure_id=?",@id)['name']
! end
! def name=(n)
! @dbh.do("update measure set name=? where measure_id=?",n,@id)
! notify_observers
! n
end
def to_s
! name
end
end
***************
*** 94,98 ****
attr_reader :id
- attr_accessor :measure, :food, :quantity, :modifier
def initialize(dbh,ingredient_id)
--- 121,124 ----
***************
*** 102,128 ****
@dbh = dbh
@id = ingredient_id
- rollback
end
! def commit
! @dbh.do("update ingredient set measure_id=?,food_id=?,quantity=?,modifier=? where ingredient_id=?",
! @measure.id, @food.id, @quantity, @modifier, @id)
! @dbh.commit
! changed
end
! def rollback
! # revert to DB state
! row = @dbh.select_one("select * from ingredient where ingredient_id=?",@id)
! @measure = $replicator.get('measure', row['measure_id'])
! @food = $replicator.get('food', row['food_id'])
! @quantity = row['quantity']
! @modifier = row['modifier']
! changed
end
def to_s
! s = "#{@quantity} #{@measure} #{@food}"
! s += " (#{@modifier})" if @modifier
return s
end
--- 128,173 ----
@dbh = dbh
@id = ingredient_id
end
! def measure
! $replicator.get('measure',@dbh.select_one("select measure_id from ingredient where ingredient_id=?",@id)['measure_id'])
! end
! def measure=(m)
! @dbh.do("update ingredient set measure_id=? where ingredient_id=?", m.id, @id)
! notify_observers
! m
end
! def food
! $replicator.get('food',@dbh.select_one("select food_id from ingredient where ingredient_id=?",@id)['food_id'])
! end
! def food=(f)
! @dbh.do("update ingredient set food_id=? where ingredient_id=?", f.id, @id)
! notify_observers
! f
! end
!
! def quantity
! @dbh.select_one("select quantity from ingredient where ingredient_id=?",@id)['quantity']
! end
! def quantity=(q)
! @dbh.do("update ingredient set quantity=? where ingredient_id=?", q, @id)
! notify_observers
! q
! end
!
! def modifier
! @dbh.select_one("select modifier from ingredient where ingredient_id=?",@id)['modifier']
! end
! def modifier=(m)
! @dbh.do("update ingredient set modifier=? where ingredient_id=?", m, @id)
! notify_observers
! m
end
def to_s
! s = "#{quantity} #{measure} #{food}"
! m = modifier
! s += " (#{m})" if m
return s
end
***************
*** 133,137 ****
attr_reader :id
! attr_accessor :name, :author, :yields, :tottime, :temp, :directions, :note, :ingredients
def initialize(dbh, recipe_id)
raise "Invalid DBH" if not dbh.kind_of?(DBI::DatabaseHandle)
--- 178,182 ----
attr_reader :id
! attr_accessor :ingredients
def initialize(dbh, recipe_id)
raise "Invalid DBH" if not dbh.kind_of?(DBI::DatabaseHandle)
***************
*** 140,177 ****
@dbh = dbh
@id = recipe_id
! rollback
end
! def commit
! @dbh.do("update recipe set name=?,author=?,serves=?,yields=?,preptime=?,tottime=?,temp=?,directions=?,note=? where recipe_id=?",
! @name, @author, @serves, @yields, @preptime, @tottime, @temp, @directions, @note, @id)
! # which measures were previously in the DB?
! @old_ingredients = Array.new
! @dbh.select_all("select ingredient_id from ingredient where recipe_id=?",@id).each do |row|
! @old_ingredients << $replicator.get('ingredient', row['ingredient_id'])
! end
! # add any new ones to the DB
! (@ingredients - @old_ingredients).each do |ingredient|
! @dbh.do("update ingredient set recipe_id=? where ingredient_id=?",@id,ingredient.id)
! end
! # remove any no longer used from the DB
! (@old_ingredients - @ingredients).each do |ingredient|
! @dbh.do("delete from ingredient where ingredient_id=?",ingredient.id)
! end
! @dbh.commit
! changed
end
! def rollback
! # revert to DB state
! @ingredients = Array.new
! @dbh.select_all("select ingredient_id from ingredient where recipe_id=?", @id).each do |row|
! @ingredients << $replicator.get('ingredient', row['ingredient_id'])
! end
! @name,@author,@yields,@tottime,@temp,@directions,@note = @dbh.select_one("select name,author,yields,tottime,temp,directions,note from recipe where recipe_id=?", @id)
! changed
end
end
--- 185,272 ----
@dbh = dbh
@id = recipe_id
! @ingredients = ObservableArray.new
! @dbh.select_all("select ingredient_id from ingredient where recipe_id=?", @id).each do |row|
! @ingredients << $replicator.get('ingredient', row['ingredient_id'])
! end
! @ingredients.add_observer {
! # which ingredients were previously in the DB?
! old_ingredients = Array.new
! @dbh.select_all("select ingredient_id from ingredient where recipe_id=?",@id).each do |row|
! old_ingredients << $replicator.get('ingredient', row['ingredient_id'])
! end
!
! # add any new ones to the DB
! (@ingredients - old_ingredients).each do |ingredient|
! @dbh.do("update ingredient set recipe_id=? where ingredient_id=?",@id,ingredient.id)
! end
!
! # remove any no longer used from the DB
! (old_ingredients - @ingredients).each do |ingredient|
! @dbh.do("delete from ingredient where ingredient_id=?",ingredient.id)
! end
! }
end
! def name
! @dbh.select_one("select name from recipe where recipe_id=?", @id)[0]
! end
! def name=(o)
! @dbh.do("update recipe set name=? where recipe_id=?", o, @id)
! notify_observers
! o
! end
! def author
! @dbh.select_one("select author from recipe where recipe_id=?", @id)[0]
! end
! def author=(o)
! @dbh.do("update recipe set author=? where recipe_id=?", o, @id)
! notify_observers
! o
! end
! def yields
! @dbh.select_one("select yields from recipe where recipe_id=?", @id)[0]
! end
! def yields=(o)
! @dbh.do("update recipe set yields=? where recipe_id=?", o, @id)
! notify_observers
! o
! end
! def tottime
! @dbh.select_one("select tottime from recipe where recipe_id=?", @id)[0]
! end
! def tottime=(o)
! @dbh.do("update recipe set tottime=? where recipe_id=?", o, @id)
! notify_observers
! o
end
! def temp
! @dbh.select_one("select temp from recipe where recipe_id=?", @id)[0]
! end
! def temp=(o)
! @dbh.do("update recipe set temp=? where recipe_id=?", o, @id)
! notify_observers
! o
! end
!
! def directions
! @dbh.select_one("select directions from recipe where recipe_id=?", @id)[0]
! end
! def directions=(o)
! @dbh.do("update recipe set directions=? where recipe_id=?", o, @id)
! notify_observers
! o
! end
!
! def note
! @dbh.select_one("select note from recipe where recipe_id=?", @id)[0]
! end
! def note=(o)
! @dbh.do("update recipe set note=? where recipe_id=?", o, @id)
! notify_observers
! o
end
end
***************
*** 181,185 ****
attr_reader :id
! attr_accessor :name, :recipes
def initialize(dbh, category_id)
--- 276,280 ----
attr_reader :id
! attr_accessor :recipes
def initialize(dbh, category_id)
***************
*** 189,226 ****
@dbh = dbh
@id = category_id
! rollback
! end
!
! def commit
! @dbh.do("update category set name=? where category_id=?", @name, @id)
! @dbh.commit
!
! # which associations were previously in the DB?
! @old_recipes = Array.new
@dbh.select_all("select recipe_id from recipe_category where category_id=?",@id).each do |row|
! @old_recipes << $replicator.get('recipe', row['recipe_id'])
end
! # add any new ones to the DB
! (@recipes - @old_recipes).each do |recipe|
! @dbh.do("insert into recipe_category (category_id,recipe_id) values (?,?)",@id,recipe.id)
! @dbh.commit
! end
! # remove any no longer used from the DB
! (@old_recipes - @recipes).each do |recipe|
! @dbh.do("delete from recipe_category where category_id=? and recipe_id=?",@id,recipe.id)
! @dbh.commit
! end
! changed
end
! def rollback
! @recipes = Array.new
! @dbh.select_all("select recipe_id from recipe_category where category_id=?",@id).each do |row|
! @recipes << $replicator.get('recipe', row['recipe_id'])
! end
! @name = @dbh.select_one("select name from category where category_id=?",@id)['name']
! changed
end
end
--- 284,319 ----
@dbh = dbh
@id = category_id
! @recipes = ObservableArray.new
@dbh.select_all("select recipe_id from recipe_category where category_id=?",@id).each do |row|
! @recipes << $replicator.get('recipe', row['recipe_id'])
end
+ @recipes.add_observer {
+ # which associations were previously in the DB?
+ old_recipes = []
+ @dbh.select_all("select recipe_id from recipe_category where category_id=?",@id).each do |row|
+ old_recipes << $replicator.get('recipe', row['recipe_id'])
+ end
! # add any new ones to the DB
! (@recipes - old_recipes).each do |recipe|
! @dbh.do("insert into recipe_category (category_id,recipe_id) values (?,?)",@id,recipe.id)
! @dbh.commit
! end
! # remove any no longer used from the DB
! (old_recipes - @recipes).each do |recipe|
! @dbh.do("delete from recipe_category where category_id=? and recipe_id=?",@id,recipe.id)
! @dbh.commit
! end
! }
end
! def name
! @dbh.select_one("select name from category where category_id=?", @id)[0]
! end
! def name=(o)
! @dbh.do("update category set name=? where category_id=?", o, @id)
! notify_observers
! o
end
end
***************
*** 230,234 ****
attr_reader :id
! attr_accessor :name, :categories
def initialize(dbh, cookbook_id)
--- 323,327 ----
attr_reader :id
! attr_accessor :categories
def initialize(dbh, cookbook_id)
***************
*** 238,275 ****
@dbh = dbh
@id = cookbook_id
! rollback
! end
!
! def commit
! @dbh.do("update cookbook set name=? where cookbook_id=?", @name, @id)
!
! # which recipes were previously in the DB?
! @old_categories = Array.new
@dbh.select_all("select category_id from category where cookbook_id=?",@id).each do |row|
! @old_categories << $replicator.get('category', row['category_id'])
end
! # add any new ones to the DB
! (@categories - @old_categories).each do |category|
! @dbh.do("update category set cookbook_id=? where category_id=?",@id,category.id)
! end
! # remove any no longer used from the DB
! (@old_categories - @categories).each do |category|
! @dbh.do("delete from category where category_id=?",category.id)
! @dbh.do("delete from recipe_category where category_id=?",category.id)
! end
! @dbh.commit
! changed
end
! def rollback
! # revert to DB state
! @categories = Array.new
! @dbh.select_all("select category_id from category where cookbook_id=?",@id).each do |row|
! @categories << $replicator.get('category', row['category_id'])
! end
! @name = @dbh.select_one("select name from cookbook where cookbook_id=?",@id)['name']
! changed
end
end
--- 331,365 ----
@dbh = dbh
@id = cookbook_id
! @categories = ObservableArray.new
@dbh.select_all("select category_id from category where cookbook_id=?",@id).each do |row|
! @categories << $replicator.get('category', row['category_id'])
end
+ @categories.add_observer {
+ # which recipes were previously in the DB?
+ old_categories = []
+ @dbh.select_all("select category_id from category where cookbook_id=?",@id).each do |row|
+ old_categories << $replicator.get('category', row['category_id'])
+ end
! # add any new ones to the DB
! (@categories - old_categories).each do |category|
! @dbh.do("update category set cookbook_id=? where category_id=?",@id,category.id)
! end
! # remove any no longer used from the DB
! (old_categories - @categories).each do |category|
! @dbh.do("delete from category where category_id=?",category.id)
! @dbh.do("delete from recipe_category where category_id=?",category.id)
! end
! }
end
! def name
! @dbh.select_one("select name from cookbook where cookbook_id=?",@id)['name']
! end
! def name=(o)
! @dbh.do("update cookbook set name=? where cookbook_id=?", o, @id)
! notify_observers
! o
end
end
|
|
From: <fu...@us...> - 2003-12-15 20:11:58
|
Update of /cvsroot/neelix/neelix/view
In directory sc8-pr-cvs1:/tmp/cvs-serv13260/view
Modified Files:
fox.rb
Log Message:
model.rb got a major overhaul. Took out all the commit/rollback stuff
(artifacts of an old paradigm), and tied the accessors directly to the db.
Added a nifty ObservableArray with many thanks to bartsman on #ruby-lang and a
few posts on comp.lang.ruby
The recipe name is complete in all its MVP glory. When you change the name of
the recipe in the form on the right, the variable is updated. Recipe then
notifies its observers (i.e. the FXTreeItem corresponding to the recipe) that
it has changed, and then the tree item updates with the new value.
Index: fox.rb
===================================================================
RCS file: /cvsroot/neelix/neelix/view/fox.rb,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** fox.rb 14 Dec 2003 04:54:05 -0000 1.3
--- fox.rb 15 Dec 2003 20:11:54 -0000 1.4
***************
*** 9,12 ****
--- 9,15 ----
name = FXTextField.new(self, 80)
name.text = recipe.name
+ name.connect(SEL_COMMAND) do |sender,sel,data|
+ recipe.name = name.text
+ end
FXLabel.new(self,"Author")
***************
*** 59,63 ****
shelf = FXGroupBox.new(splitter,"Shelf",FRAME_GROOVE)
! shelf.width = 200
counter = FXGroupBox.new(splitter,"Counter",FRAME_GROOVE)
--- 62,66 ----
shelf = FXGroupBox.new(splitter,"Shelf",FRAME_GROOVE)
! shelf.width=200
counter = FXGroupBox.new(splitter,"Counter",FRAME_GROOVE)
***************
*** 71,74 ****
--- 74,78 ----
item.data = recipe
shelfTree.addItemLast(category_item, item)
+ recipe.add_observer { item.text = recipe.name; shelfTree.update }
end
end
|
|
From: <fu...@us...> - 2003-12-14 10:52:48
|
Update of /cvsroot/neelix/neelix/model
In directory sc8-pr-cvs1:/tmp/cvs-serv22349/model
Modified Files:
model.rb
Log Message:
In the middle of major refactoring for the GUI. The GUI as a result is less
functional than before, but much cleaner.
Index: model.rb
===================================================================
RCS file: /cvsroot/neelix/neelix/model/model.rb,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** model.rb 12 Dec 2003 22:50:47 -0000 1.1
--- model.rb 13 Dec 2003 17:56:48 -0000 1.2
***************
*** 3,8 ****
--- 3,11 ----
require 'dbi'
require 'singleton'
+ require 'observer'
class Food
+ include Observable
+
attr_reader :id
attr_accessor :name, :measures
***************
*** 38,41 ****
--- 41,45 ----
@dbh.commit
end
+ changed
end
***************
*** 46,49 ****
--- 50,54 ----
end
@name = @dbh.select_one("select name from food where food_id=?",@id)['name']
+ changed
end
***************
*** 54,57 ****
--- 59,64 ----
class Measure
+ include Observable
+
attr_reader :id
attr_accessor :name
***************
*** 69,72 ****
--- 76,80 ----
@dbh.do("update measure set name=? where measure_id=?",@name,@id)
@dbh.commit
+ changed
end
***************
*** 74,77 ****
--- 82,86 ----
# revert to DB state
@name = @dbh.select_one("select name from measure where measure_id=?",@id)['name']
+ changed
end
***************
*** 82,85 ****
--- 91,96 ----
class Ingredient
+ include Observable
+
attr_reader :id
attr_accessor :measure, :food, :quantity, :modifier
***************
*** 98,101 ****
--- 109,113 ----
@measure.id, @food.id, @quantity, @modifier, @id)
@dbh.commit
+ changed
end
***************
*** 107,110 ****
--- 119,123 ----
@quantity = row['quantity']
@modifier = row['modifier']
+ changed
end
***************
*** 117,120 ****
--- 130,135 ----
class Recipe
+ include Observable
+
attr_reader :id
attr_accessor :name, :author, :yields, :tottime, :temp, :directions, :note, :ingredients
***************
*** 148,151 ****
--- 163,167 ----
end
@dbh.commit
+ changed
end
***************
*** 157,164 ****
--- 173,183 ----
end
@name,@author,@yields,@tottime,@temp,@directions,@note = @dbh.select_one("select name,author,yields,tottime,temp,directions,note from recipe where recipe_id=?", @id)
+ changed
end
end
class Category
+ include Observable
+
attr_reader :id
attr_accessor :name, :recipes
***************
*** 194,200 ****
@dbh.commit
end
end
- # revert to DB state
def rollback
@recipes = Array.new
--- 213,219 ----
@dbh.commit
end
+ changed
end
def rollback
@recipes = Array.new
***************
*** 203,210 ****
--- 222,232 ----
end
@name = @dbh.select_one("select name from category where category_id=?",@id)['name']
+ changed
end
end
class Cookbook
+ include Observable
+
attr_reader :id
attr_accessor :name, :categories
***************
*** 239,242 ****
--- 261,265 ----
end
@dbh.commit
+ changed
end
***************
*** 248,251 ****
--- 271,275 ----
end
@name = @dbh.select_one("select name from cookbook where cookbook_id=?",@id)['name']
+ changed
end
end
***************
*** 254,257 ****
--- 278,282 ----
class Replicator
include Singleton
+
attr_accessor :shelf
|
|
From: <fu...@us...> - 2003-12-14 09:43:02
|
Update of /cvsroot/neelix/neelix/view
In directory sc8-pr-cvs1:/tmp/cvs-serv22078/view
Modified Files:
fox.rb
Log Message:
More GUI refactoring. Achieved recipe view. Now need to add recipe presenter,
and view updating (with observer pattern)
Index: fox.rb
===================================================================
RCS file: /cvsroot/neelix/neelix/view/fox.rb,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** fox.rb 13 Dec 2003 17:56:48 -0000 1.2
--- fox.rb 14 Dec 2003 04:54:05 -0000 1.3
***************
*** 2,26 ****
include Fox
class NeelixMainWindow < FXMainWindow
def initialize(app)
! super(app, 'Neelix',nil,nil,DECOR_ALL,0,0,800,600)
frame = FXHorizontalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y)
splitter = FXSplitter.new(frame,SPLITTER_HORIZONTAL|LAYOUT_FILL_X|LAYOUT_FILL_Y)
! groupbox = FXGroupBox.new(splitter,"Shelf",FRAME_GROOVE)
counter = FXGroupBox.new(splitter,"Counter",FRAME_GROOVE)
! frame = FXVerticalFrame.new(groupbox,LAYOUT_FILL_X|LAYOUT_FILL_Y)
! shelf = FXTreeList.new(frame,0,nil,0,TREELIST_SINGLESELECT|TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|LAYOUT_FILL_X|LAYOUT_FILL_Y)
$replicator.shelf.each do |cookbook|
! cookbook_item = shelf.addItemLast(nil, FXTreeItem.new(cookbook.name))
! cookbook_item.expanded = true
cookbook.categories.each do |category|
! category_item = shelf.addItemLast(cookbook_item, FXTreeItem.new(category.name))
category.recipes.each do |recipe|
! shelf.addItemLast(category_item, FXTreeItem.new(recipe.name))
end
end
end
end
end
--- 2,88 ----
include Fox
+ class RecipeForm < FXVerticalFrame
+ def initialize(parent,recipe)
+ super(parent)
+
+ FXLabel.new(self,"Name")
+ name = FXTextField.new(self, 80)
+ name.text = recipe.name
+
+ FXLabel.new(self,"Author")
+ author = FXTextField.new(self, 80)
+ author.text = recipe.author
+
+ FXLabel.new(self,"Oven Temp.")
+ temp = FXTextField.new(self, 80)
+ temp.text = recipe.temp
+
+ FXLabel.new(self,"Total Time")
+ tottime = FXTextField.new(self, 80)
+ tottime.text = recipe.tottime
+
+ FXLabel.new(self,"Yields")
+ yields = FXTextField.new(self, 80)
+ yields.text = recipe.yields
+
+ FXLabel.new(self,"Ingredients")
+ frame = FXHorizontalFrame.new(self,LAYOUT_FILL_X)
+ ingredientList = FXList.new(frame,recipe.ingredients.size,nil,0,LAYOUT_FILL_X)
+ frame = FXVerticalFrame.new(frame)
+ FXButton.new(frame,"Add Ingredient")
+ up = FXButton.new(frame,"Move Up")
+ down = FXButton.new(frame,"Move Down")
+ up.enabled = false
+ down.enabled = false
+ recipe.ingredients.each do |ingredient|
+ ingredientList.appendItem(ingredient.to_s)
+ end
+
+ FXLabel.new(self,"Directions")
+ directions = FXText.new(self)
+ directions.visCols=80
+ directions.text = recipe.directions
+
+ FXLabel.new(self,"Notes")
+ notes = FXText.new(self)
+ notes.visCols=80
+ notes.text = recipe.note
+ end
+ end
+
class NeelixMainWindow < FXMainWindow
def initialize(app)
! super(app, 'Neelix')
! resize(800,600)
frame = FXHorizontalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y)
splitter = FXSplitter.new(frame,SPLITTER_HORIZONTAL|LAYOUT_FILL_X|LAYOUT_FILL_Y)
! shelf = FXGroupBox.new(splitter,"Shelf",FRAME_GROOVE)
! shelf.width = 200
counter = FXGroupBox.new(splitter,"Counter",FRAME_GROOVE)
! shelfTree = FXTreeList.new(shelf,0,nil,0,TREELIST_SINGLESELECT|TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|LAYOUT_FILL_X|LAYOUT_FILL_Y)
$replicator.shelf.each do |cookbook|
! cookbook_item = shelfTree.addItemLast(nil, FXTreeItem.new(cookbook.name))
cookbook.categories.each do |category|
! category_item = shelfTree.addItemLast(cookbook_item, FXTreeItem.new(category.name))
category.recipes.each do |recipe|
! item = FXTreeItem.new(recipe.name)
! item.data = recipe
! shelfTree.addItemLast(category_item, item)
end
end
end
+ shelfTree.connect(SEL_SELECTED) do |sender,sel,ptr|
+ if Recipe === ptr.data
+ counter.children.each { |child| counter.removeChild(child) }
+ RecipeForm.new(counter,ptr.data).create
+ end
+ end
+
+ shelfTree.expandTree(shelfTree.firstItem)
+ shelfTree.expandTree(shelfTree.firstItem.first)
+ shelfTree.makeItemVisible(shelfTree.firstItem.first.first)
+
end
end
|
|
From: <fu...@us...> - 2003-12-14 09:41:51
|
Update of /cvsroot/neelix/neelix/db In directory sc8-pr-cvs1:/tmp/cvs-serv21770 Modified Files: Makefile pbj.sql Added Files: hans.sql Log Message: PBJ still broken. Use the hans database. Just run make in db/ and then run ./neelix db/hans.db --- NEW FILE: hans.sql --- BEGIN TRANSACTION; -- CREATE TABLE category ( -- category_id INTEGER NOT NULL PRIMARY KEY, -- cookbook_id INTEGER NOT NULL, -- name varchar(80) -- ); INSERT INTO category VALUES(1,1,'Bread'); INSERT INTO category VALUES(2,1,'Sourdough Bread'); -- CREATE TABLE cookbook ( -- cookbook_id INTEGER NOT NULL PRIMARY KEY, -- name varchar(80) -- ); INSERT INTO cookbook VALUES(1,'Hans'' Cookbook'); -- CREATE TABLE food ( -- food_id INTEGER NOT NULL PRIMARY KEY, -- name varchar(80) -- ); INSERT INTO food VALUES(1,'Whole Wheat Flour'); INSERT INTO food VALUES(2,'Water'); INSERT INTO food VALUES(3,'Instant Yeast'); INSERT INTO food VALUES(4,'Salt'); INSERT INTO food VALUES(5,'Sourdough Start'); INSERT INTO food VALUES(6,'Honey'); -- CREATE TABLE food_measures ( -- food_id INTEGER NOT NULL, -- measure_id INTEGER NOT NULL, -- grams float, -- ccs float -- ); -- CREATE TABLE ingredient ( -- ingredient_id INTEGER NOT NULL PRIMARY KEY, -- recipe_id INTEGER NOT NULL, -- measure_id INTEGER NOT NULL, -- food_id INTEGER NOT NULL, -- quantity float, -- modifier varchar(80) -- ); INSERT INTO ingredient VALUES(1,1,1,5,720,'Active, 100% Hydration'); INSERT INTO ingredient VALUES(2,1,1,1,540,''); INSERT INTO ingredient VALUES(3,1,1,2,295,NULL); INSERT INTO ingredient VALUES(4,1,2,4,2,NULL); -- CREATE TABLE measure ( -- measure_id INTEGER NOT NULL PRIMARY KEY, -- name varchar(80) -- ); INSERT INTO measure VALUES(1,'grams'); INSERT INTO measure VALUES(2,'teaspoons'); -- CREATE TABLE recipe ( -- recipe_id INTEGER NOT NULL PRIMARY KEY, -- name varchar(80), -- author varchar(80), -- serves varchar(80), -- yields varchar(80), -- preptime varchar(80), -- tottime varchar(80), -- temp varchar(80), -- directions text, -- note text -- ); INSERT INTO recipe VALUES(1,'Basic Whole Wheat Sourdough Bread','Hans Fugal',NULL,'2 loaves',NULL,NULL,NULL,'Knead, let rise, shape and let rise, bake.','Based off the basic whole wheat bread recipe in Laurel''s Kitchen Bread Book.'); -- CREATE TABLE recipe_category ( -- recipe_id INTEGER NOT NULL, -- category_id INTEGER NOT NULL -- ); INSERT INTO recipe_category VALUES(1,2); COMMIT; Index: Makefile =================================================================== RCS file: /cvsroot/neelix/neelix/db/Makefile,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Makefile 12 Dec 2003 22:47:05 -0000 1.1 --- Makefile 13 Dec 2003 17:55:41 -0000 1.2 *************** *** 2,6 **** XSL=db.xsl ! all: pbj.db empty.db: db.xml --- 2,6 ---- XSL=db.xsl ! all: hans.db empty.db: db.xml Index: pbj.sql =================================================================== RCS file: /cvsroot/neelix/neelix/db/pbj.sql,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pbj.sql 12 Dec 2003 22:47:05 -0000 1.1 --- pbj.sql 13 Dec 2003 17:55:41 -0000 1.2 *************** *** 1,2 **** --- 1,4 ---- + -- NOTE this is broken. use hans.sql... + -- -- Dumping data for table 'food' |
|
From: <fu...@us...> - 2003-12-14 09:41:47
|
Update of /cvsroot/neelix/neelix
In directory sc8-pr-cvs1:/tmp/cvs-serv22349
Modified Files:
neelix.rb
Log Message:
In the middle of major refactoring for the GUI. The GUI as a result is less
functional than before, but much cleaner.
Index: neelix.rb
===================================================================
RCS file: /cvsroot/neelix/neelix/neelix.rb,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** neelix.rb 12 Dec 2003 22:50:47 -0000 1.3
--- neelix.rb 13 Dec 2003 17:56:48 -0000 1.4
***************
*** 8,13 ****
usage unless ARGV[0]
- require 'fox'
require 'dbi'
# This is where you might put a check for another type of UI - e.g. ncurses
--- 8,16 ----
usage unless ARGV[0]
require 'dbi'
+ require 'model/model.rb'
+
+ dbh = DBI.connect("dbi:sqlite:#{ARGV[0]}")
+ $replicator.attach(dbh)
# This is where you might put a check for another type of UI - e.g. ncurses
|
|
From: <fu...@us...> - 2003-12-14 08:51:10
|
Update of /cvsroot/neelix/neelix/model
In directory sc8-pr-cvs1:/tmp/cvs-serv22078/model
Modified Files:
model.rb
Log Message:
More GUI refactoring. Achieved recipe view. Now need to add recipe presenter,
and view updating (with observer pattern)
Index: model.rb
===================================================================
RCS file: /cvsroot/neelix/neelix/model/model.rb,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** model.rb 13 Dec 2003 17:56:48 -0000 1.2
--- model.rb 14 Dec 2003 04:54:05 -0000 1.3
***************
*** 123,127 ****
def to_s
! s = "#{@quantity}\t#{@measure}\t#{@food}"
s += " (#{@modifier})" if @modifier
return s
--- 123,127 ----
def to_s
! s = "#{@quantity} #{@measure} #{@food}"
s += " (#{@modifier})" if @modifier
return s
|
|
From: <fu...@us...> - 2003-12-14 08:51:10
|
Update of /cvsroot/neelix/neelix/db In directory sc8-pr-cvs1:/tmp/cvs-serv22057/db Modified Files: hans.sql Log Message: Refined the recipes a tad. Index: hans.sql =================================================================== RCS file: /cvsroot/neelix/neelix/db/hans.sql,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** hans.sql 13 Dec 2003 17:55:41 -0000 1.1 --- hans.sql 14 Dec 2003 04:52:46 -0000 1.2 *************** *** 5,10 **** -- name varchar(80) -- ); ! INSERT INTO category VALUES(1,1,'Bread'); ! INSERT INTO category VALUES(2,1,'Sourdough Bread'); -- CREATE TABLE cookbook ( -- cookbook_id INTEGER NOT NULL PRIMARY KEY, --- 5,11 ---- -- name varchar(80) -- ); ! INSERT INTO category VALUES(1,1,'Sourdough Bread'); ! INSERT INTO category VALUES(2,1,'Whole Wheat Bread'); ! INSERT INTO category VALUES(3,1,'White Bread'); -- CREATE TABLE cookbook ( -- cookbook_id INTEGER NOT NULL PRIMARY KEY, *************** *** 22,25 **** --- 23,27 ---- INSERT INTO food VALUES(5,'Sourdough Start'); INSERT INTO food VALUES(6,'Honey'); + INSERT INTO food VALUES(7,'Oil'); -- CREATE TABLE food_measures ( -- food_id INTEGER NOT NULL, *************** *** 37,49 **** -- ); INSERT INTO ingredient VALUES(1,1,1,5,720,'Active, 100% Hydration'); ! INSERT INTO ingredient VALUES(2,1,1,1,540,''); INSERT INTO ingredient VALUES(3,1,1,2,295,NULL); INSERT INTO ingredient VALUES(4,1,2,4,2,NULL); -- CREATE TABLE measure ( -- measure_id INTEGER NOT NULL PRIMARY KEY, -- name varchar(80) -- ); ! INSERT INTO measure VALUES(1,'grams'); ! INSERT INTO measure VALUES(2,'teaspoons'); -- CREATE TABLE recipe ( -- recipe_id INTEGER NOT NULL PRIMARY KEY, --- 39,61 ---- -- ); INSERT INTO ingredient VALUES(1,1,1,5,720,'Active, 100% Hydration'); ! INSERT INTO ingredient VALUES(2,1,1,1,540,NULL); INSERT INTO ingredient VALUES(3,1,1,2,295,NULL); INSERT INTO ingredient VALUES(4,1,2,4,2,NULL); + + INSERT INTO ingredient VALUES(5,2,2,3,2,NULL); + INSERT INTO ingredient VALUES(6,2,4,2,120,'warm'); + INSERT INTO ingredient VALUES(7,2,1,1,900,NULL); + INSERT INTO ingredient VALUES(8,2,2,4,2.5,NULL); + INSERT INTO ingredient VALUES(9,2,4,2,535,'lukewarm'); + INSERT INTO ingredient VALUES(10,2,3,6,2,NULL); + INSERT INTO ingredient VALUES(11,2,3,7,2,NULL); -- CREATE TABLE measure ( -- measure_id INTEGER NOT NULL PRIMARY KEY, -- name varchar(80) -- ); ! INSERT INTO measure VALUES(1,'g'); ! INSERT INTO measure VALUES(2,'tsp'); ! INSERT INTO measure VALUES(3,'Tbsp'); ! INSERT INTO measure VALUES(4,'ml'); -- CREATE TABLE recipe ( -- recipe_id INTEGER NOT NULL PRIMARY KEY, *************** *** 58,66 **** -- note text -- ); ! INSERT INTO recipe VALUES(1,'Basic Whole Wheat Sourdough Bread','Hans Fugal',NULL,'2 loaves',NULL,NULL,NULL,'Knead, let rise, shape and let rise, bake.','Based off the basic whole wheat bread recipe in Laurel''s Kitchen Bread Book.'); -- CREATE TABLE recipe_category ( -- recipe_id INTEGER NOT NULL, -- category_id INTEGER NOT NULL -- ); ! INSERT INTO recipe_category VALUES(1,2); COMMIT; --- 70,80 ---- -- note text -- ); ! INSERT INTO recipe VALUES(1,'Whole Wheat Sourdough Bread','Hans Fugal',NULL,'2 loaves',NULL,NULL,NULL,'Knead, let rise, shape and let rise, bake.','Based off the basic whole wheat bread recipe in Laurel''s Kitchen Bread Book.'); ! INSERT INTO recipe VALUES(2,'Whole Wheat Bread','Hans Fugal',NULL,'2 loaves',NULL,NULL,NULL,'Knead, let rise, shape and let rise, bake.','Based off of basic whole wheat bread from Laurel''s Kitchen Bread Book.'); -- CREATE TABLE recipe_category ( -- recipe_id INTEGER NOT NULL, -- category_id INTEGER NOT NULL -- ); ! INSERT INTO recipe_category VALUES(1,1); ! INSERT INTO recipe_category VALUES(2,2); COMMIT; |
|
From: <fu...@us...> - 2003-12-14 08:40:39
|
Update of /cvsroot/neelix/neelix/view
In directory sc8-pr-cvs1:/tmp/cvs-serv22349/view
Modified Files:
fox.rb
Log Message:
In the middle of major refactoring for the GUI. The GUI as a result is less
functional than before, but much cleaner.
Index: fox.rb
===================================================================
RCS file: /cvsroot/neelix/neelix/view/fox.rb,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** fox.rb 12 Dec 2003 22:50:47 -0000 1.1
--- fox.rb 13 Dec 2003 17:56:48 -0000 1.2
***************
*** 1,263 ****
include Fox
- require 'model/model.rb'
-
- class CookbookForm < FXPacker
- def initialize(parent, cookbook)
- super(parent)
-
- FXLabel.new(self,"Name ")
-
- dt = cookbook.targets['name']
- name = FXTextField.new(self, 80, dt, FXDataTarget::ID_VALUE)
-
- FXButton.new(self,"Accept").connect(SEL_COMMAND) do
- cookbook.commit
- end
- end
- end
-
- class CategoryForm < FXPacker
- def initialize(parent, category)
- super(parent)
-
- FXLabel.new(self,"Name ")
- dt = category.targets['name']
- name = FXTextField.new(self, 80,dt,DT::ID_VALUE)
-
- FXButton.new(self,"Accept").connect(SEL_COMMAND) do
- category.commit
- end
- end
- end
-
- class RecipeForm < FXPacker
- def initialize(parent, recipe)
- super(parent)
-
- FXLabel.new(self,"Name")
- dt = recipe.targets['name']
- name = FXTextField.new(self, 80,dt,DT::ID_VALUE)
-
- FXLabel.new(self,"by")
- dt = recipe.targets['author']
- author = FXTextField.new(self, 80,dt,DT::ID_VALUE)
-
- FXLabel.new(self,"Prep and Cook Time")
- dt = recipe.targets['tottime']
- tottime = FXTextField.new(self, 80,dt,DT::ID_VALUE)
-
- FXLabel.new(self,"Makes")
- dt = recipe.targets['yields']
- yields = FXTextField.new(self, 80,dt,DT::ID_VALUE)
-
- FXLabel.new(self,"Oven Temp")
- dt = recipe.targets['temp']
- temp = FXTextField.new(self, 80,dt,DT::ID_VALUE)
-
- # The ingredients table shall always have an empty row, ie it grows as
- # the user enters ingredients. It may have more than one empty row, but
- # of course the database only updated by non-empty rows.
- FXLabel.new(self,"Ingredients")
- ingred_table = FXTable.new(self,6,4,nil,0)
- ingred_table.setTableSize(recipe.ingredients.size+2,4)
- ingred_table.leadingRows = 1
- cols = ["Quantity","Measure","Ingredient","Modifier"]
- (0..3).each { |c|
- ingred_table.setItemText(0,c,cols[c])
- }
- (0..recipe.ingredients.size).each { |r|
- next if r >= recipe.ingredients.size
- ingredient = recipe.ingredients[r]
- ingred_table.setItemText(r+1,0,ingredient.quantity.to_s)
- ingred_table.setItemText(r+1,1,ingredient.measure.to_s)
- ingred_table.setItemText(r+1,2,ingredient.food.to_s)
- ingred_table.setItemText(r+1,3,ingredient.modifier.to_s)
- }
-
- FXLabel.new(self,"Directions")
- directions = FXText.new(self)
- directions.text = recipe.directions
-
- FXLabel.new(self,"Note")
- note = FXText.new(self)
- note.text = recipe.note
-
- FXButton.new(self,"Accept").connect(SEL_COMMAND) do
- # these text fields aren't connected to DataTargets
- recipe.directions = directions.text
- recipe.note = note.text
- recipe.commit
- end
- end
- end
-
- class BlankForm < FXLabel
- def initialize(parent, assocObj)
- super(parent, '')
- end
- end
-
class NeelixMainWindow < FXMainWindow
def initialize(app)
! # initialize base class
! super(app, "Neelix", nil, nil, DECOR_ALL, 0, 0, 800, 600)
!
! # set up main window contents, etc.
! contents = FXHorizontalFrame.new(self, LAYOUT_FILL_X| LAYOUT_FILL_Y)
! splitter = FXSplitter.new(contents,
! LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y|
! SPLITTER_HORIZONTAL)
! # create the shelf (nav tree)
! @shelf = Shelf.new(splitter)
$replicator.shelf.each do |cookbook|
! cookbook_item = @shelf.addItem(nil, cookbook.name,
! proc { |item|
! @counter.current.tab.target = cookbook.targets['name']
! @counter.current.tab.selector = DT::ID_VALUE
! @counter.current.tab.text = cookbook.name
! @counter.current.item = item
! children = @counter.current.page.children
! children.each { |child|
! @counter.current.page.removeChild(child)
! }
! CookbookForm.new(@counter.current.page, cookbook).create
! })
cookbook.categories.each do |category|
! category_item = @shelf.addItem(cookbook_item, category.name,
! proc { |item|
! @counter.current.tab.target = category.targets['name']
! @counter.current.tab.selector = DT::ID_VALUE
! @counter.current.tab.text = category.name
! @counter.current.item = item
! children = @counter.current.page.children
! children.each { |child|
! @counter.current.page.removeChild(child)
! }
! CategoryForm.new(@counter.current.page, category).create
! })
category.recipes.each do |recipe|
! @shelf.addItem(category_item, recipe.name,
! proc { |item|
! @counter.current.tab.target = recipe.targets['name']
! @counter.current.tab.selector = DT::ID_VALUE
! @counter.current.tab.text = recipe.name
! @counter.current.item = item
! children = @counter.current.page.children
! children.each { |child|
! @counter.current.page.removeChild(child)
! }
! RecipeForm.new(@counter.current.page, recipe).create
! })
! end
! end
! end
!
! # create the counter (tabs)
! @counter = Counter.new(splitter)
!
! myProc = proc do |item|
! @shelf.tree.selectItem(item) unless item.nil?
! end
!
! tab = @counter.addTab('Shelf', nil, myProc)
! BlankForm.new(tab.page, nil)
! end
! end
!
! class Shelf < FXGroupBox
! attr_reader :tree
! def initialize(parent)
! super(parent, "Cookbook Shelf", LAYOUT_FILL_X| LAYOUT_FILL_Y| FRAME_GROOVE)
! frame = FXVerticalFrame.new(self, LAYOUT_FILL_X| LAYOUT_FILL_Y)
!
! @procs = Hash.new
! @tree = FXTreeList.new(frame, 0, nil, 0,
! TREELIST_SINGLESELECT| TREELIST_SHOWS_LINES|
! TREELIST_SHOWS_BOXES| TREELIST_ROOT_BOXES| LAYOUT_FILL_Y|
! LAYOUT_FILL_X)
!
! @tree.connect(SEL_COMMAND) do |sender, sel, item|
! getApp().beginWaitCursor do
! if not item.equal?(@current) then
! @current = item
! @procs[item].call(item)
! end
! end
! end
!
! @current = nil
! end
! def create
! super
! setWidth(@tree.font.getTextWidth('MMMMMMMMMMMMMMMM'))
! end
! def addItem(parentItem, text, assocProc = proc { })
! item = FXTreeItem.new(text)
! @tree.addItemLast(parentItem, item)
! @procs[item] = assocProc
! return item
! end
! end
!
! class Counter < FXTabBook
! attr_reader :current
! def initialize(parent)
! super(parent, nil, 0, LAYOUT_FILL_X| LAYOUT_FILL_Y| LAYOUT_RIGHT)
!
! self.connect(SEL_COMMAND) do |sender, sel, index|
! getApp().beginWaitCursor do
! if not @current.equal?(@tabs[index])
! @current = @tabs[index]
! @current.activate
end
end
end
-
- @tabs = Array.new
- @current = nil
- end
- def addTab(title, assocItem = nil, assocProc = proc { })
- tab = CounterTab.new(self, title, assocItem, assocProc)
- @tabs << tab
- @current = tab if @current.nil?
- return tab
end
end
! class CounterTab
! attr_reader :tab, :page, :item
! def initialize(parent, title, assocItem, assocProc)
! @tab = FXTabItem.new(parent, title)
! @page = FXHorizontalFrame.new(parent, FRAME_RAISED)
! @item = assocItem
! @proc = assocProc
! @content = nil
! end
! def activate
! @proc.call(@item)
! end
! def setContent(contentClass, contentArg)
! if not @content.nil? then
! # do something to get rid of existing content
! end
! #@content = contentClass.new(self, contentArg)
! end
! def item=(item)
! @item = item
! end
!
! end
!
! # main()
! dbh = DBI.connect("dbi:sqlite:#{ARGV[0]}")
! $replicator.attach(dbh)
! application = FXApp.new('Neelix', 'Fugal')
! application.init(ARGV)
! neelix = NeelixMainWindow.new(application)
! application.create
neelix.show
! application.run
--- 1,34 ----
+ require 'fox'
include Fox
class NeelixMainWindow < FXMainWindow
def initialize(app)
! super(app, 'Neelix',nil,nil,DECOR_ALL,0,0,800,600)
! frame = FXHorizontalFrame.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y)
! splitter = FXSplitter.new(frame,SPLITTER_HORIZONTAL|LAYOUT_FILL_X|LAYOUT_FILL_Y)
! groupbox = FXGroupBox.new(splitter,"Shelf",FRAME_GROOVE)
! counter = FXGroupBox.new(splitter,"Counter",FRAME_GROOVE)
+ frame = FXVerticalFrame.new(groupbox,LAYOUT_FILL_X|LAYOUT_FILL_Y)
+ shelf = FXTreeList.new(frame,0,nil,0,TREELIST_SINGLESELECT|TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|LAYOUT_FILL_X|LAYOUT_FILL_Y)
$replicator.shelf.each do |cookbook|
! cookbook_item = shelf.addItemLast(nil, FXTreeItem.new(cookbook.name))
! cookbook_item.expanded = true
cookbook.categories.each do |category|
! category_item = shelf.addItemLast(cookbook_item, FXTreeItem.new(category.name))
category.recipes.each do |recipe|
! shelf.addItemLast(category_item, FXTreeItem.new(recipe.name))
end
end
end
end
end
! app = FXApp.new('Neelix', 'fugalh')
! app.init(ARGV)
! neelix = NeelixMainWindow.new(app)
! app.create
neelix.show
! app.run
|
|
From: Hans F. <ha...@fu...> - 2003-12-12 22:52:39
|
I've done some major refactoring. See the commit log. You might want to check out into a different directory esp. if you've made any changes as most of the files have been moved around and CVS doesn't handle that well. This has made the GUI uninteresting (i.e. there's no data and no way to change it). Fixing that is the next step. --=20 Hans Fugal | De gustibus non disputandum est. http://hans.fugal.net/ | Debian, vim, mutt, ruby, text, gpg http://gdmxml.fugal.net/ | WindowMaker, gaim, UTF-8, RISC, JS Bach --------------------------------------------------------------------- GnuPG Fingerprint: 6940 87C5 6610 567F 1E95 CB5E FC98 E8CD E0AA D460 |
|
From: Hans F. <ha...@fu...> - 2003-12-12 21:37:30
|
/* Quoth Jamis Buck <jg...@em...> on Fri, 12 Dec 2003 at 12:43 -0700 in <3FD...@em...> */ > >On the MVC issue, can anyone give me a good reason why view and > >controller are separate? Some suggest tightly coupling them and I really > >am having a hard time figuring out the benefit in keeping them separate. >=20 > For what it's worth, Danny and I have been taking 456 (GUI's) this=20 > semester, and Dr. Olsen is of the opinion that there is no added value=20 > in separating the view from the controller. He said that it used to be= =20 > done, but caused a lot more complexity for few additional benefits. =20 > Also, he said that the only reason for separating the view from the=20 > controller is if you want to reuse the controller or view independently= =20 > of one another (ie, attach the same view to a different controller, or=20 > vice versa). This happens extremely rarely. =46rom more reading I've done, I think another aspect at play is that what with the toolkits we have nowdays the controller aspect is usually extremely simple and very tightly coupled with the view (also done with the same toolkit. in fact some widgets are both controllers _and_ views). I just read about the Model-View-Presenter model[1] and I really like that approach. It almost exactly maps onto the four-layer architecture[2] as well. 1. http://www.object-arts.com/EducationCentre/Overviews/ModelViewPresenter.= htm 2. http://c2.com/cgi/wiki?FourLayerArchitecture --=20 Hans Fugal | De gustibus non disputandum est. http://hans.fugal.net/ | Debian, vim, mutt, ruby, text, gpg http://gdmxml.fugal.net/ | WindowMaker, gaim, UTF-8, RISC, JS Bach --------------------------------------------------------------------- GnuPG Fingerprint: 6940 87C5 6610 567F 1E95 CB5E FC98 E8CD E0AA D460 |
|
From: Jamis B. <jg...@em...> - 2003-12-12 19:44:32
|
Hans Fugal wrote: >In summary, the replicator is the gate to the model. The view and >controller get to the model (set of objects) via the replicator. Views >register as observers to keep up-to-date. > > This sounds a lot like what I did for Penny Pincher (a Swing-based financial tool I've been working on: http://penny-pincher.sf.net), at least as far as the observers. I created a DatabaseEventMediator, and anytime anyone changed the database in anyway, they notified the DEM and told it which table and record (or records) were modified. Then, any objects that were registered listeners on the given table were notified of the change. Works quite well. >On the MVC issue, can anyone give me a good reason why view and >controller are separate? Some suggest tightly coupling them and I really >am having a hard time figuring out the benefit in keeping them separate. > > For what it's worth, Danny and I have been taking 456 (GUI's) this semester, and Dr. Olsen is of the opinion that there is no added value in separating the view from the controller. He said that it used to be done, but caused a lot more complexity for few additional benefits. Also, he said that the only reason for separating the view from the controller is if you want to reuse the controller or view independently of one another (ie, attach the same view to a different controller, or vice versa). This happens extremely rarely. - Jamis -- Jamis Buck jg...@em... ruby -h | ruby -e 'a=[];readlines.join.scan(/-(.)\[e|Kk(\S*)|le.l(..)e|#!(\S*)/) {|r| a << r.compact.first };puts "\n>#{a.join(%q/ /)}<\n\n"' |
|
From: Hans F. <ha...@fu...> - 2003-12-12 19:33:15
|
I should add I forgot to include the Shelf, which is an aggregation of cookbooks. While I'm explaining things I'll touch on the Replicator, which is a fun little creation of ours. The replicator is basically a factory pattern. You ask it for (type,id) and it gives you the corresponding object. It may already have that object, or it may have to create an object from the database. It also has a create method to add objects to the database. So, if you get your objects from the replicator always there will only ever be one object with the same (type,id), and it will keep itself in sync with the db, but we do not have to create all the objects up front (surely it will be rare that you look at every recipe during one invocation of the program - we save some time and memory however negligible it might be). In MVC it's fairly standard for the model to notify the view when it has changed (i.e. observer pattern). I think each object in the model will have a registry of observers (objects in the view) that get notified on change (e.g. when an object in the controller changes a value, or any model-internal processes do the same, although that's not likely to happen in neelix). This will nicely address the datatarget issues Jacob and I were trying to work out earlier. It was getting pretty hairy. In summary, the replicator is the gate to the model. The view and controller get to the model (set of objects) via the replicator. Views register as observers to keep up-to-date. On the MVC issue, can anyone give me a good reason why view and controller are separate? Some suggest tightly coupling them and I really am having a hard time figuring out the benefit in keeping them separate. Maybe as I read more[1]... 1.=A0http://st-www.cs.uiuc.edu/users/smarch/st-docs/mvc.html /* Quoth Hans Fugal <ha...@fu...> on Fri, 12 Dec 2003 at 12:08 -0700 in <200...@fa...> */ > Made this with umbrello. Umbrello was pretty cool until it segfaulted > when I exported this image, before I got the chance to save my work. >=20 > This is more or less the data model that neelix does and will use. It > reflects the database schema as well. I left out the attr_accessors for > aggregations, leaving that up to the imagination via the aggregation > associations. Also note that quantity should be public just like all the > other accessors.=20 >=20 > You might notice I made the accessors attributes. I love how ruby blurs > the distinction between an attribute and its accessor. >=20 > --=20 > Hans Fugal | De gustibus non disputandum est. > http://hans.fugal.net/ | Debian, vim, mutt, ruby, text, gpg > http://gdmxml.fugal.net/ | WindowMaker, gaim, UTF-8, RISC, JS Bach > --------------------------------------------------------------------- > GnuPG Fingerprint: 6940 87C5 6610 567F 1E95 CB5E FC98 E8CD E0AA D460 --=20 Hans Fugal | De gustibus non disputandum est. http://hans.fugal.net/ | Debian, vim, mutt, ruby, text, gpg http://gdmxml.fugal.net/ | WindowMaker, gaim, UTF-8, RISC, JS Bach --------------------------------------------------------------------- GnuPG Fingerprint: 6940 87C5 6610 567F 1E95 CB5E FC98 E8CD E0AA D460 |
|
From: Hans F. <ha...@fu...> - 2003-12-12 19:08:21
|
Made this with umbrello. Umbrello was pretty cool until it segfaulted when I exported this image, before I got the chance to save my work. This is more or less the data model that neelix does and will use. It reflects the database schema as well. I left out the attr_accessors for aggregations, leaving that up to the imagination via the aggregation associations. Also note that quantity should be public just like all the other accessors. You might notice I made the accessors attributes. I love how ruby blurs the distinction between an attribute and its accessor. -- Hans Fugal | De gustibus non disputandum est. http://hans.fugal.net/ | Debian, vim, mutt, ruby, text, gpg http://gdmxml.fugal.net/ | WindowMaker, gaim, UTF-8, RISC, JS Bach --------------------------------------------------------------------- GnuPG Fingerprint: 6940 87C5 6610 567F 1E95 CB5E FC98 E8CD E0AA D460 |
|
From: Hans F. <ha...@fu...> - 2003-12-12 05:22:31
|
I took the liberty of adding you all to this list. Welcome. :) I want to have something usable (version 0.1.0) for my wife for Christmas, so I'm going to be pushing neelix hard over the next couple weeks. If you are up to it let me know. If you are just curious watch CVS. If you are busy, look over things after Christmas. :) Since I've been away from the code for awhile I realize how badly organized it really is. My first task is going to be refactoring. I'm going to follow a basic MVC pattern. This will make alternative controllers/views (e.g. byron's ncurses gui) easier to develop. The Model itself will have two tiers - the data tier and the database tier. This is already mostly in place. --=20 Hans Fugal | De gustibus non disputandum est. http://hans.fugal.net/ | Debian, vim, mutt, ruby, text, gpg http://gdmxml.fugal.net/ | WindowMaker, gaim, UTF-8, RISC, JS Bach --------------------------------------------------------------------- GnuPG Fingerprint: 6940 87C5 6610 567F 1E95 CB5E FC98 E8CD E0AA D460 |