· 8 years ago · Feb 21, 2018, 09:58 AM
1
2New patches:
3
4[removing the standard rflc.rb
5manveru@weez-int.com**20061015125611] {
6hunk ./lib/rflc.rb 1
7-Dir['rflc/**/*.rb'].sort.each { |lib| require lib }
8+
9rmfile ./lib/rflc.rb
10}
11
12[adapt the whole RFLC-app to the new structure, also adds the RFLC-namespace, execute the app now via ./bin/rflc (make executable first or use 'ruby bin/rflc') - if you use gem install rflc you can just run 'rflc' which is placed in your bin-dir
13manveru@weez-int.com**20061015140236] {
14move ./lib/rflc/main.rb ./lib/rflc.rb
15adddir ./lib/rflc/ui
16hunk ./bin/rflc 1
17-#!/bin/sh
18+#!/usr/bin/env ruby
19+$:.unshift File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib')
20hunk ./bin/rflc 4
21-#
22-# rflc: rflc.sh
23-#
24-# Launcher script for rflc
25-#
26+p $:
27hunk ./bin/rflc 6
28-cd lib/rflc/
29-exec ruby main.rb
30-# redirect stderr to /dev/null
31-#exec ruby main.rb 2>/dev/null
32+require 'rflc'
33hunk ./bin/rflc 8
34-exit
35+RFLC.run
36hunk ./lib/rflc.rb 9
37-$RFLC_Main = true
38+require 'rflc/config'
39+require 'rflc/ui'
40hunk ./lib/rflc.rb 12
41-require 'ui.rb'
42-require 'config.rb'
43+module RFLC
44+ CONFIG = Config.new
45+ UI = Ui.new
46hunk ./lib/rflc.rb 16
47-# def main
48-# --------
49-#
50-def main()
51- # open the config file
52- $RFLC_Config = RFLC_Config.new
53- $RFLC_Config.load( "../../design/example.config" )
54-
55- # create the user interface
56- $RFLC_Ui = RFLC_UI.new
57-
58- $RFLC_Ui.run
59-
60- return
61+ def self.run
62+ UI.run
63+ end
64hunk ./lib/rflc.rb 21
65-main()
66-
67-exit
68-
69hunk ./lib/rflc/check.rb 1
70-#
71-# rflc: check.rb
72-#
73-# This file should be included in the header of every not directly
74-# executable source file, as it checks if the file has been included
75-# through main.rb or not.
76-#
77-
78-if not $RFLC_Main
79- puts "You need to run `main.rb' to use RFLC!"
80-
81- exit
82-end
83rmfile ./lib/rflc/check.rb
84hunk ./lib/rflc/config.rb 7
85-require 'check.rb'
86-
87hunk ./lib/rflc/config.rb 8
88-
89-require 'deck.rb'
90+require 'rflc/deck'
91hunk ./lib/rflc/config.rb 16
92-class RFLC_Config
93- attr_accessor :decks
94- attr_reader :filename
95+module RFLC
96+ class Config
97+ attr_accessor :decks
98+ attr_reader :filename
99hunk ./lib/rflc/config.rb 21
100- # def initialize()
101- # --------------
102- # Initialize the stack
103- def initialize
104- @decks = Array.new
105+ # def initialize()
106+ # --------------
107+ # Initialize the stack
108+ def initialize
109+ @decks = Array.new
110+ end
111hunk ./lib/rflc/config.rb 28
112- return
113- end
114+ # def count?
115+ # ---------
116+ # Returns the number of decks loaded
117+ def count?
118+ @decks.length
119+ end
120hunk ./lib/rflc/config.rb 35
121- # def count?
122- # ---------
123- # Returns the number of decks loaded
124- def count?
125- return @decks.length
126- end
127+ # def load( file )
128+ # ----------------
129+ # Loads a config file and parses it. If the current Config object has any
130+ # deck entries, they will be replaced by the new entries read from
131+ # the config file. The file can be gzipped or clear-text.
132+ # The function will raise an IOError, if the file is not found or can not
133+ # be accessed.
134+ #
135+ # file path to the file in filesystem
136+ def load( file )
137+ @filename = file
138+ fd = nil
139hunk ./lib/rflc/config.rb 48
140- # def load( file )
141- # ----------------
142- # Loads a config file and parses it. If the current Config object has any
143- # deck entries, they will be replaced by the new entries read from
144- # the config file. The file can be gzipped or clear-text.
145- # The function will raise an IOError, if the file is not found or can not
146- # be accessed.
147- #
148- # file path to the file in filesystem
149- def load( file )
150- @filename = file
151- fd = nil
152+ # check to see if the file exists and is readable
153+ unless File.file?(file) and File.readable?(file)
154+ # if not, raise an exception
155+ raise IOError, "The file #{file} could not be accessed!"
156+ end
157hunk ./lib/rflc/config.rb 54
158- # check to see if the file exists and is readable
159- if (!File.file?(file)) or (!File.readable?(file))
160- # if not, raise an exception
161- raise IOError, "The file " + file + " could not be accessed!"
162- return
163- end
164-
165- # open the file for reading
166- if file.slice( -3, 3 ) == ".gz"
167- fd = Zlib::GzipReader.open( file )
168- else
169- fd = File.open( file, "r" )
170- end
171+ # open the file for reading
172+ if File.ext(file) == '.gz'
173+ fd = Zlib::GzipReader.open( file )
174+ else
175+ fd = File.open( file, "r" )
176+ end
177hunk ./lib/rflc/config.rb 61
178- # let YAML parse it for us <3
179- yaml = YAML.load_stream( fd )
180- doc = yaml.documents[0]
181+ # let YAML parse it for us <3
182+ yaml = YAML.load_stream( fd )
183+ doc = yaml.documents[0]
184hunk ./lib/rflc/config.rb 65
185- # loop through the entries
186- doc.each do |key, value|
187- # go through the decks
188- case key
189- when "decks"
190- value.each do |d|
191- deck = RFLC_Deck.new
192- deck.load( d )
193- @decks.push( deck )
194- end # each card
195- end
196- end # each entry
197-
198- return
199- end
200+ # loop through the entries
201+ doc.each do |key, value|
202+ # go through the decks
203+ case key
204+ when "decks"
205+ value.each do |d|
206+ deck = RFLC_Deck.new
207+ deck.load( d )
208+ @decks.push( deck )
209+ end # each card
210+ end
211+ end # each entry
212+ end
213+ end
214hunk ./lib/rflc/config_test.rb 1
215-#!/usr/bin/ruby
216hunk ./lib/rflc/config_test.rb 3
217-$RFLC_Main = true
218+require 'rflc/config'
219+require 'rflc/flashcard'
220+require 'rflc/deck'
221hunk ./lib/rflc/config_test.rb 7
222-require 'config.rb'
223-require 'flashcard.rb'
224-require 'deck.rb'
225-
226-config = RFLC_Config.new
227+config = RFLC::Config.new
228hunk ./lib/rflc/deck.rb 11
229-require 'check.rb'
230-
231hunk ./lib/rflc/deck.rb 14
232-require 'flashcard.rb'
233-require 'util.rb'
234+require 'rflc/flashcard'
235+require 'rflc/util'
236hunk ./lib/rflc/deck.rb 25
237-class RFLC_Deck
238- attr_accessor :name, :description
239- attr_reader :filename
240-
241- # def initialize()
242- # --------------
243- # Initialize the stack
244- def initialize
245- @deck = Array.new
246-
247- return
248- end
249-
250- # def push( card )
251- # ----------------
252- # Add a flashcard to the top of the deck
253- #
254- # card A Flashcard struct to be put on top of the stack
255- def push( card )
256- # FIXME: should we check for the object's type before adding it,
257- # check that it really is a Flashcard?
258- @deck.push( card )
259-
260- return
261- end
262-
263- # def pop()
264- # ---------
265- # Take a flashcard from the top and returns it
266- #
267- # Returns a Flashcard struct from the top of the deck,
268- # or nil if the deck is empty
269- def pop
270- return @deck.pop
271- end
272-
273- # def count?
274- # ----------
275- # Returns the number of flashcards in the deck
276- def count?
277- return @deck.length
278- end
279+module RFLC
280+ class Deck
281+ attr_accessor :name, :description
282+ attr_reader :filename
283hunk ./lib/rflc/deck.rb 30
284- # def ccount?
285- # -----------
286- # Returns the number of checked flashcards in the deck
287- def ccount?
288- count = 0
289- @deck.each do |word|
290- if word.checked == true
291- count += 1
292- end
293- end
294+ # def initialize()
295+ # --------------
296+ # Initialize the stack
297+ def initialize
298+ @deck = Array.new
299+ end
300hunk ./lib/rflc/deck.rb 37
301- return count
302- end
303+ # def push( card )
304+ # ----------------
305+ # Add a flashcard to the top of the deck
306+ #
307+ # card A Flashcard struct to be put on top of the stack
308+ def push( card )
309+ # FIXME: should we check for the object's type before adding it,
310+ # check that it really is a Flashcard?
311+ # maybe check if it implements the right interface only...
312+ @deck.push( card ) if card.is_a? FlashCard
313+ end
314hunk ./lib/rflc/deck.rb 49
315- # def search( query )
316- # -------------------
317- # Search the deck for flashcards. The query can be either a flashcard
318- # object or a string. If the query is flashcard, search for other similar
319- # flashcards (the same kana, kanji or meaning). If the query is a string,
320- # search for a flashcard that hase the same kana, kanji or meaning.
321- #
322- # query The search query, an object of type either Flashcard or String
323- #
324- # Returns the results as an array of Flashcard objects
325- def search( query )
326- results = Array.new
327+ # def pop()
328+ # ---------
329+ # Take a flashcard from the top and returns it
330+ #
331+ # Returns a Flashcard struct from the top of the deck,
332+ # or nil if the deck is empty
333+ def pop
334+ @deck.pop
335+ end
336hunk ./lib/rflc/deck.rb 59
337- # check to see if the query is a Flashard or a String
338- if (query.respond_to? :kana) \
339- and (query.respond_to? :kanji) \
340- and (query.respond_to? :meanings)
341- # the query is a flashcard
342- flashcard = true
343- query_kana = query.kana
344- query_kanji = query.kanji
345- query_meaning = query.meanings
346- else
347- # the query is a string
348- flashcard = false
349- query_kana = query_kanji = query_meaning = query
350- end
351+ # def count?
352+ # ----------
353+ # Returns the number of flashcards in the deck
354+ def count?
355+ @deck.length
356+ end
357hunk ./lib/rflc/deck.rb 66
358- # search
359- @deck.each do |card|
360- # see if kana or kanji are the same
361- if (card.kana == query_kana) or (card.kanji == query_kanji)
362- results.push( card )
363- else
364- # search for a similar meaning
365- card.meanings.each do |meaning|
366- if meaning.match( ".*" + query_meaning + ".*" )
367- results.push( card )
368- end
369- end # end of similar meaning search
370- end
371- end # end of the search
372+ # def ccount?
373+ # -----------
374+ # Returns the number of checked flashcards in the deck
375+ def ccount?
376+ @deck.select{|word| word.checked}.size
377+ end
378hunk ./lib/rflc/deck.rb 73
379- return results
380- end
381+ # def search( query )
382+ # -------------------
383+ # Search the deck for flashcards. The query can be either a flashcard
384+ # object or a string. If the query is flashcard, search for other similar
385+ # flashcards (the same kana, kanji or meaning). If the query is a string,
386+ # search for a flashcard that hase the same kana, kanji or meaning.
387+ #
388+ # query The search query, an object of type either Flashcard or String
389+ #
390+ # Returns the results as an array of Flashcard objects
391+ def search( query )
392+ results = Array.new
393hunk ./lib/rflc/deck.rb 86
394- # def load( file )
395- # ----------------
396- # Loads a deck file and parses it. If the current Deck object has any
397- # flashcard entries, they will be replaced by the new entries read from
398- # the deck file. The file can be gzipped or clear-text.
399- # The function will raise an IOError, if the file is not found or can not
400- # be accessed.
401- #
402- # file path to the file in filesystem
403- def load( file )
404- @filename = file
405- fd = nil
406+ # check to see if the query is a Flashard or a String
407+ if (query.respond_to? :kana) \
408+ and (query.respond_to? :kanji) \
409+ and (query.respond_to? :meanings)
410+ # the query is a flashcard
411+ flashcard = true
412+ query_kana = query.kana
413+ query_kanji = query.kanji
414+ query_meaning = query.meanings
415+ else
416+ # the query is a string
417+ flashcard = false
418+ query_kana = query_kanji = query_meaning = query
419+ end
420hunk ./lib/rflc/deck.rb 101
421- # check to see if the file exists and is readable
422- if (!File.file?(file)) or (!File.readable?(file))
423- # if not, raise an exception
424- raise IOError, "The file " + file + " could not be accessed!"
425- return
426- end
427-
428- # open the file for reading
429- if file.slice( -3, 3 ) == ".gz"
430- fd = Zlib::GzipReader.open( file )
431- else
432- fd = File.open( file, "r" )
433- end
434+ # search
435+ @deck.each do |card|
436+ # see if kana or kanji are the same
437+ if (card.kana == query_kana) or (card.kanji == query_kanji)
438+ results.push( card )
439+ else
440+ # search for a similar meaning
441+ card.meanings.each do |meaning|
442+ if meaning.match( ".*" + query_meaning + ".*" )
443+ results.push( card )
444+ end
445+ end # end of similar meaning search
446+ end
447+ end # end of the search
448hunk ./lib/rflc/deck.rb 116
449- # let YAML parse it for us <3
450- yaml = YAML.load_stream( fd )
451- doc = yaml.documents[0]
452+ return results
453+ end
454hunk ./lib/rflc/deck.rb 119
455- # loop through the entries
456- doc.each do |key, value|
457- # go through the cards
458- case key
459- when "name"
460- @name = value
461+ # def load( file )
462+ # ----------------
463+ # Loads a deck file and parses it. If the current Deck object has any
464+ # flashcard entries, they will be replaced by the new entries read from
465+ # the deck file. The file can be gzipped or clear-text.
466+ # The function will raise an IOError, if the file is not found or can not
467+ # be accessed.
468+ #
469+ # file path to the file in filesystem
470+ def load( file )
471+ @filename = file
472+ fd = nil
473hunk ./lib/rflc/deck.rb 132
474- when "description"
475- @description = value
476+ # check to see if the file exists and is readable
477+ if (!File.file?(file)) or (!File.readable?(file))
478+ # if not, raise an exception
479+ raise IOError, "The file " + file + " could not be accessed!"
480+ return
481+ end
482hunk ./lib/rflc/deck.rb 139
483- when "cards"
484- value.each do |c|
485- card = RFLC_Flashcard.new
486+ # open the file for reading
487+ if file.slice( -3, 3 ) == ".gz"
488+ fd = Zlib::GzipReader.open( file )
489+ else
490+ fd = File.open( file, "r" )
491+ end
492hunk ./lib/rflc/deck.rb 146
493- c.each do |k, v|
494- case k
495- when "meanings"
496- v.each do |meaning|
497- card.add_meaning( meaning )
498- end # each meaning
499+ # let YAML parse it for us <3
500+ yaml = YAML.load_stream( fd )
501+ doc = yaml.documents[0]
502hunk ./lib/rflc/deck.rb 150
503- when "examples"
504- v.each do |example|
505- card.add_example( example[0], example[1] )
506- end # each example
507+ # loop through the entries
508+ doc.each do |key, value|
509+ # go through the cards
510+ case key
511+ when "name"
512+ @name = value
513hunk ./lib/rflc/deck.rb 157
514- when "kana"
515- card.kana = v
516+ when "description"
517+ @description = value
518hunk ./lib/rflc/deck.rb 160
519- when "kanji"
520- card.kanji = v
521+ when "cards"
522+ value.each do |c|
523+ card = RFLC_Flashcard.new
524hunk ./lib/rflc/deck.rb 164
525- when "checked"
526- card.checked = v
527+ c.each do |k, v|
528+ case k
529+ when "meanings"
530+ v.each do |meaning|
531+ card.add_meaning( meaning )
532+ end # each meaning
533hunk ./lib/rflc/deck.rb 171
534- when "type"
535- card.type = v
536- end
537- end # each card value
538+ when "examples"
539+ v.each do |example|
540+ card.add_example( example[0], example[1] )
541+ end # each example
542hunk ./lib/rflc/deck.rb 176
543- self.push( card )
544- end # each card
545- end
546- end # each entry
547-
548- return
549- end
550+ when "kana", "kanji", "checked", "type"
551+ card.send("#{k}=", v)
552+ end
553+ end # each card value
554hunk ./lib/rflc/deck.rb 181
555- # def each()
556- # ----------
557- # Block loop through every card
558- def each()
559- @deck.each { |card| yield card }
560+ self.push( card )
561+ end # each card
562+ end
563+ end # each entry
564hunk ./lib/rflc/deck.rb 186
565- return
566- end
567+ return
568+ end
569hunk ./lib/rflc/deck.rb 189
570- def []( i )
571- return @deck[i]
572- end
573+ # def each()
574+ # ----------
575+ # Block loop through every card
576+ def each()
577+ @deck.each { |card| yield card }
578+ end
579hunk ./lib/rflc/deck.rb 196
580- # def shuffle()
581- # -------------
582- # This is to shuffle the deck
583- def shuffle
584- @deck.shuffle
585+ def []( i )
586+ @deck[i]
587+ end
588hunk ./lib/rflc/deck.rb 200
589- return
590- end
591+ # def shuffle()
592+ # -------------
593+ # This is to shuffle the deck
594+ def shuffle
595+ @deck.shuffle
596+ end
597+ end
598hunk ./lib/rflc/flashcard.rb 8
599-require 'check.rb'
600-
601hunk ./lib/rflc/flashcard.rb 34
602-class RFLC_Flashcard
603- attr_accessor :kana, :kanji, :meanings, :examples, :type, :checked
604-
605- # def initialise()
606- # ----------------
607- # Initialize the flashcard
608- def initialize()
609- @kana = @kanji = ""
610- @meanings = Array.new
611- @examples = Array.new
612- @type = ""
613- @checked = true
614-
615- return
616- end
617-
618- # def add_meaning( meaning )
619- # ------------------------------------
620- # A wrapper function for adding a new meaning to the word
621- #
622- # japanese The example in Japanese encoded as UTF-8
623- # english The example in English
624- def add_meaning( meaning )
625- @meanings.push( meaning )
626+module RFLC
627+ class Flashcard
628+ attr_accessor :kana, :kanji, :meanings, :examples, :type, :checked
629hunk ./lib/rflc/flashcard.rb 38
630- return
631- end
632+ # def initialise()
633+ # ----------------
634+ # Initialize the flashcard
635+ def initialize()
636+ @kana = @kanji = ""
637+ @meanings = Array.new
638+ @examples = Array.new
639+ @type = ""
640+ @checked = true
641+ end
642hunk ./lib/rflc/flashcard.rb 49
643- # def add_example( japanese, english )
644- # ------------------------------------
645- # A wrapper function for adding a new example to the flashcard
646- #
647- # japanese The example in Japanese encoded as UTF-8
648- # english The example in English
649- def add_example( japanese, english )
650- @examples.push( Struct::RFLC_Example.new(japanese, english) )
651+ # def add_meaning( meaning )
652+ # ------------------------------------
653+ # A wrapper function for adding a new meaning to the word
654+ #
655+ # japanese The example in Japanese encoded as UTF-8
656+ # english The example in English
657+ def add_meaning( meaning )
658+ @meanings.push( meaning )
659+ end
660hunk ./lib/rflc/flashcard.rb 59
661- return
662- end
663+ # def add_example( japanese, english )
664+ # ------------------------------------
665+ # A wrapper function for adding a new example to the flashcard
666+ #
667+ # japanese The example in Japanese encoded as UTF-8
668+ # english The example in English
669+ def add_example( japanese, english )
670+ @examples.push( Struct::RFLC_Example.new(japanese, english) )
671+ end
672+ end
673hunk ./lib/rflc/ui.rb 7
674-require 'check.rb'
675-
676hunk ./lib/rflc/ui.rb 9
677-require 'ui_select_deck.rb'
678+require 'rflc/ui/select_deck'
679hunk ./lib/rflc/ui.rb 21
680-class RFLC_UI
681- attr_accessor :view, :window
682+module RFLC
683+ class Ui
684+ attr_accessor :view, :window
685hunk ./lib/rflc/ui.rb 25
686- # def initialize()
687- # ----------------
688- # Creates the UI objects, but doesn't show them yet
689- def initialize()
690- # remember to init GTK+!
691- Gtk.init()
692+ # def initialize()
693+ # ----------------
694+ # Creates the UI objects, but doesn't show them yet
695+ def initialize()
696+ # remember to init GTK+!
697+ Gtk.init()
698hunk ./lib/rflc/ui.rb 32
699- # select deck view
700- select_deck = RFLC_UI_Select_Deck.new
701- @view = Gtk::Frame.new
702- @view.add( select_deck.vbox )
703- @view.set_shadow_type( Gtk::SHADOW_NONE )
704+ # select deck view
705+ select_deck = RFLC::UI_Select_Deck.new
706+ @view = Gtk::Frame.new
707+ @view.add( select_deck.vbox )
708+ @view.set_shadow_type( Gtk::SHADOW_NONE )
709hunk ./lib/rflc/ui.rb 38
710- # create menus
711- @menu = Gtk::MenuBar.new
712- menuitem = Gtk::MenuItem.new( "_Application" )
713- @menu.append menuitem
714- menuitem = Gtk::MenuItem.new( "_View" )
715- @menu.append menuitem
716- menuitem = Gtk::MenuItem.new( "_Options" )
717- @menu.append menuitem
718+ # create menus
719+ @menu = Gtk::MenuBar.new
720+ menuitem = Gtk::MenuItem.new( "_Application" )
721+ @menu.append menuitem
722+ menuitem = Gtk::MenuItem.new( "_View" )
723+ @menu.append menuitem
724+ menuitem = Gtk::MenuItem.new( "_Options" )
725+ @menu.append menuitem
726hunk ./lib/rflc/ui.rb 47
727- # the main vbox
728- @vbox = Gtk::VBox.new
729- @vbox.pack_start( @menu, false, true, 0 )
730- @vbox.pack_start( @view, true, true, 0 )
731+ # the main vbox
732+ @vbox = Gtk::VBox.new
733+ @vbox.pack_start( @menu, false, true, 0 )
734+ @vbox.pack_start( @view, true, true, 0 )
735hunk ./lib/rflc/ui.rb 52
736- # create the main window
737- @window = Gtk::Window.new
738- @window.signal_connect( "destroy" ) { window_destroy() }
739- @window.set_title( "RFLC" )
740- @window.add( @vbox )
741+ # create the main window
742+ @window = Gtk::Window.new
743+ @window.signal_connect( "destroy" ) { window_destroy() }
744+ @window.set_title( "RFLC" )
745+ @window.add( @vbox )
746hunk ./lib/rflc/ui.rb 58
747- return
748- end
749+ return
750+ end
751hunk ./lib/rflc/ui.rb 61
752- # def run()
753- # ---------
754- # Shows the UI and runs the GTK+ main loop
755- def run()
756- # show the UI
757- @window.show_all
758+ # def run()
759+ # ---------
760+ # Shows the UI and runs the GTK+ main loop
761+ def run()
762+ # show the UI
763+ @window.show_all
764hunk ./lib/rflc/ui.rb 68
765- # GTK+ main loop
766- Gtk.main
767+ # GTK+ main loop
768+ Gtk.main
769hunk ./lib/rflc/ui.rb 71
770- return
771- end
772+ return
773+ end
774hunk ./lib/rflc/ui.rb 74
775- # --- Callbacks ---------------------------------------------------------
776+ # --- Callbacks ---------------------------------------------------------
777hunk ./lib/rflc/ui.rb 76
778- # def window_destroy()
779- # --------------------
780- # This callback is fired when the main window is destroyed.
781- # Quits the program when main window is closed.
782- def window_destroy()
783- Gtk.main_quit
784+ # def window_destroy()
785+ # --------------------
786+ # This callback is fired when the main window is destroyed.
787+ # Quits the program when main window is closed.
788+ def window_destroy()
789+ Gtk.main_quit
790hunk ./lib/rflc/ui.rb 83
791- return
792- end
793+ return
794+ end
795+ end
796addfile ./lib/rflc/ui/deck_practice.rb
797hunk ./lib/rflc/ui/deck_practice.rb 1
798+#
799+# rflc: ui_deck_practice.rb
800+#
801+# User Interface, Practice (deck options)
802+#
803+
804+require 'gtk2'
805+
806+require 'rflc/flashcard'
807+require 'rflc/util'
808+require 'rflc/ui/flashcard'
809+require 'rflc/ui/start'
810+
811+# class UI_Deck_Practice
812+# ----------------------
813+# Main class for the User Interface
814+#
815+# public members:
816+# @vbox The main vbox which holds all the widgets
817+# private members:
818+# @deck the deck whose practice window this is
819+# @view the treeview wordlist
820+#
821+# @wlabel the word count label
822+module RFLC
823+ class UI_Deck_Practice
824+ attr_reader :vbox
825+
826+ # column indentifiers to make life easier
827+ COLUMN_CHECKED, COLUMN_KANA, COLUMN_KANJI, \
828+ COLUMN_ENGLISH, COLUMN_DATA = *(0..5).to_a
829+
830+ # def initialize()
831+ # ----------------
832+ # Create the UI objects, but don't show them yet
833+ def initialize( deck )
834+ @deck = deck
835+ @settings = Array.new
836+
837+ @settings[SETTINGS_FRONT] = 0
838+
839+ # header
840+ header = Gtk::Label.new
841+ header.set_markup( "<span size=\"xx-large\">#{@deck.name}</span>" )
842+
843+ # left side
844+
845+ description = Gtk::Label.new( @deck.description )
846+ description.set_wrap( true )
847+
848+ # flashcard view
849+ flcard = RFCL::Flashcard.new
850+ flcard.kana = "れã„"
851+ flcard.kanji = "例"
852+ flcard.add_meaning( "Example" )
853+ card = RFCL::UI_Flashcard.new( flcard )
854+ card.set_side( FLASHCARD_SIDE_FRONT )
855+ card.set_front( SETTING_KANA )
856+
857+ # card front
858+ vbox = Gtk::VBox.new
859+ radio_front = Gtk::RadioButton.new( "Show the word in ã‹ãª" )
860+ radio_front.signal_connect( "toggled", card ) do |w, card|
861+ if w.active?
862+ card.set_front( SETTING_KANA )
863+ card.redraw()
864+
865+ @settings[SETTINGS_FRONT] = SETTING_KANA
866+ end
867+ end
868+ vbox.pack_start( radio_front, false, true, 0 )
869+
870+ radio_front = Gtk::RadioButton.new( radio_front, "Show the word in æ¼¢å—" )
871+ radio_front.signal_connect( "toggled", card ) do |w, card|
872+ if w.active?
873+ card.set_front( SETTING_KANJI )
874+ card.redraw()
875+
876+ @settings[SETTINGS_FRONT] = SETTING_KANJI
877+ end
878+ end
879+ vbox.pack_start( radio_front, false, true, 0 )
880+
881+ radio_front = Gtk::RadioButton.new( radio_front, "Show the English meaning" )
882+ radio_front.signal_connect( "toggled", card ) do |w, card|
883+ if w.active?
884+ card.set_front( SETTING_ENGLISH )
885+ card.redraw()
886+
887+ @settings[SETTINGS_FRONT] = SETTING_ENGLISH
888+ end
889+ end
890+ vbox.pack_start( radio_front, false, true, 0 )
891+
892+ alignment = Gtk::Alignment.new( 0, 0, 0, 0 )
893+ alignment.set_padding( 0, 0, 10, 0 )
894+ alignment.add( vbox )
895+
896+ front_side = Gtk::Frame.new( "<b>Flashcard front side</b>" )
897+ front_side.label_widget.set_use_markup( true )
898+ front_side.add( alignment )
899+ front_side.set_shadow_type( Gtk::SHADOW_NONE )
900+
901+ # options
902+ vbox = Gtk::VBox.new
903+ check_write = Gtk::CheckButton.new( "Practice writing kanji" )
904+ check_write.signal_connect( "toggled" ) do |w|
905+ if w.active?
906+ @settings[SETTING_WRITE] = true
907+ end
908+ end
909+ vbox.pack_start( check_write, false, true, 0 )
910+
911+ check_shuffle = Gtk::CheckButton.new( "Shuffle the deck" )
912+ check_shuffle.signal_connect( "toggled" ) do |w|
913+ if w.active?
914+ @settings[SETTING_SHUFFLE] = true
915+ end
916+ end
917+ vbox.pack_start( check_shuffle, false, true, 0 )
918+
919+ alignment = Gtk::Alignment.new( 0, 0, 0, 0 )
920+ alignment.set_padding( 0, 0, 10, 0 )
921+ alignment.add( vbox )
922+
923+ options = Gtk::Frame.new( "<b>Options</b>" )
924+ options.label_widget.set_use_markup( true )
925+ options.add( alignment )
926+ options.set_shadow_type( Gtk::SHADOW_NONE )
927+
928+ vboxl = Gtk::VBox.new
929+ vboxl.pack_start( description, false, true, 5 )
930+ vboxl.pack_start( front_side, false, true, 0 )
931+ vboxl.pack_start( options, false, true, 0 )
932+ vboxl.pack_start( card.vbox, true, true, 0 )
933+
934+ # right side
935+
936+ @wlabel = Gtk::Label.new( "" )
937+ wlabel_update()
938+ wordlist = create_wordlist()
939+
940+ # (un)?select all
941+ select_all = Gtk::Button.new( "Select all" )
942+ select_all.set_relief( Gtk::RELIEF_NONE )
943+ select_all.signal_connect( "clicked" ) { select_all_clicked() }
944+
945+ unselect_all = Gtk::Button.new( "Deselect all" )
946+ unselect_all.set_relief( Gtk::RELIEF_NONE )
947+ unselect_all.signal_connect( "clicked" ) { unselect_all_clicked() }
948+
949+ hbox = Gtk::HBox.new
950+ hbox.pack_start( select_all, true, false, 0 )
951+ hbox.pack_start( unselect_all, true, false, 0 )
952+
953+ vboxr = Gtk::VBox.new
954+ vboxr.pack_start( @wlabel, false, true, 5 )
955+ vboxr.pack_start( wordlist, true, true, 0 )
956+ vboxr.pack_start( hbox, false, true, 0 )
957+
958+ # hbox
959+ hbox = Gtk::HBox.new
960+ hbox.pack_start( vboxl, false, true, 5 )
961+ hbox.pack_start( vboxr, true, true, 5 )
962+ hbox.set_border_width( 10 )
963+
964+ # separator
965+ separator = Gtk::HSeparator.new
966+
967+ # bottom bar
968+ back = Gtk::Button.new( Gtk::Stock::GO_BACK )
969+ back.set_relief( Gtk::RELIEF_NONE )
970+ back.signal_connect( "clicked" ) { back_clicked() }
971+
972+ edit = Gtk::Button.new( Gtk::Stock::EDIT )
973+ edit.set_relief( Gtk::RELIEF_NONE )
974+
975+ start = Gtk::Button.new( "Start" )
976+ start.set_image( Gtk::Image.new(Gtk::Stock::JUMP_TO,
977+ Gtk::IconSize::BUTTON) )
978+ start.set_relief( Gtk::RELIEF_NONE )
979+ start.signal_connect( "clicked" ) { start_clicked() }
980+
981+ bar = Gtk::HBox.new
982+ bar.pack_start( back, true, false, 0 )
983+ bar.pack_start( edit, true, false, 0 )
984+ bar.pack_start( start, true, false, 0 )
985+
986+ # the main vbox
987+ @vbox = Gtk::VBox.new
988+ @vbox.pack_start( header, false, false, 10 )
989+ @vbox.pack_start( hbox, true, true, 10 )
990+ @vbox.pack_start( separator, false, true, 0 )
991+ @vbox.pack_start( bar, false, true, 5 )
992+
993+ return
994+ end
995+
996+ # def create_wordlist()
997+ # ---------------------
998+ # Create the "flashcards to go through" treeview
999+ def create_wordlist()
1000+ store = Gtk::TreeStore.new( TrueClass, String, String, String,
1001+ RFLC::Flashcard )
1002+
1003+ # take the card data
1004+ @deck.each do |card|
1005+ parent = store.append( nil )
1006+ parent[COLUMN_CHECKED] = card.checked
1007+ parent[COLUMN_KANA] = card.kana
1008+ parent[COLUMN_KANJI] = card.kanji
1009+ parent[COLUMN_ENGLISH] = card.meanings.join( ", " )
1010+ parent[COLUMN_DATA] = card # not rendered (RFCL::Flashcard)
1011+ end
1012+
1013+ @view = Gtk::TreeView.new( store )
1014+
1015+ renderer = Gtk::CellRendererToggle.new
1016+ renderer.signal_connect( "toggled" ) do |cell, path|
1017+ word_toggled( @view.model, path )
1018+ end
1019+ col = Gtk::TreeViewColumn.new( "è¾¼", renderer,
1020+ :active => COLUMN_CHECKED )
1021+ @view.append_column( col )
1022+
1023+ renderer = Gtk::CellRendererText.new
1024+ col = Gtk::TreeViewColumn.new( "ã‹ãª", renderer,
1025+ :text => COLUMN_KANA )
1026+ @view.append_column( col )
1027+ col = Gtk::TreeViewColumn.new( "æ¼¢å—", renderer,
1028+ :text => COLUMN_KANJI )
1029+ @view.append_column( col )
1030+ col = Gtk::TreeViewColumn.new( "English meaning", renderer,
1031+ :text => COLUMN_ENGLISH )
1032+ @view.append_column( col )
1033+
1034+ @view.selection.mode = Gtk::SELECTION_SINGLE
1035+ @view.set_headers_clickable( true )
1036+ @view.set_enable_search( true ) # TODO: make a search function that
1037+ # matches kana, kanji and the meaning
1038+ @view.set_reorderable( true ) # FIXME: currently you can make
1039+ # sublists. Disable this and make
1040+ # saving modified decks work
1041+
1042+ # scrolled window
1043+ scrolled = Gtk::ScrolledWindow.new()
1044+ scrolled.add( @view )
1045+ scrolled.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
1046+ scrolled.set_shadow_type( Gtk::SHADOW_ETCHED_IN )
1047+
1048+ return scrolled
1049+ end
1050+
1051+ def wlabel_update()
1052+ @wlabel.set_text( "Check the words to go through: " \
1053+ + "(#{@deck.ccount?} out of #{@deck.count?})" )
1054+
1055+ return
1056+ end
1057+
1058+ # def show()
1059+ # ----------
1060+ # Shows the UI
1061+ def show()
1062+ @vbox.show_all
1063+
1064+ return
1065+ end
1066+
1067+ # --- Callbacks ---------------------------------------------------------
1068+ # def back_clicked()
1069+ # ------------------
1070+ # Back button clicked. Show Select Deck view.
1071+ def back_clicked()
1072+ select_deck = RFCL::UI_Select_Deck.new
1073+ select_deck.show
1074+
1075+ RFCL::Ui.view.remove( self.vbox )
1076+ RFCL::Ui.view.add( select_deck.vbox )
1077+
1078+ return
1079+ end
1080+
1081+ # def start_clicked()
1082+ # -------------------
1083+ # Start button clicked. Show the practicing view
1084+ def start_clicked()
1085+ # check that there's >0 cards in the deck checked
1086+ if not @deck.ccount? > 0
1087+ dialog = Gtk::MessageDialog.new( RFCL::Ui.window, \
1088+ Gtk::Dialog::DESTROY_WITH_PARENT, Gtk::MessageDialog::INFO,
1089+ Gtk::MessageDialog::BUTTONS_OK,
1090+ "You must select the cards you want to practice." )
1091+ dialog.set_title( "RFLC - Card selection" )
1092+
1093+ dialog.signal_connect( "response" ) { dialog.destroy }
1094+ dialog.show_all
1095+
1096+ return
1097+ end
1098+
1099+ # replace the view
1100+ practice = RFCL::UI_Start.new( @deck, @settings )
1101+ practice.show
1102+
1103+ RFCL::Ui.view.remove( self.vbox )
1104+ RFCL::Ui.view.add( practice.vbox )
1105+
1106+ return
1107+ end
1108+
1109+ # def word_toggled()
1110+ # ------------------
1111+ # Button toggled in the treeview
1112+ def word_toggled( model, path )
1113+ path = Gtk::TreePath.new( path )
1114+
1115+ iter = model.get_iter( path )
1116+ toggled = iter[COLUMN_CHECKED]
1117+ toggled ^= 1
1118+ iter[COLUMN_CHECKED] = toggled
1119+ iter[COLUMN_DATA].checked = toggled
1120+
1121+ wlabel_update()
1122+
1123+ return
1124+ end
1125+
1126+ # def select_all_clicked()
1127+ # ------------------------
1128+ # Check all the words in the wordlist treeview
1129+ def select_all_clicked()
1130+ @view.model.each do |model, path, iter|
1131+ iter[COLUMN_CHECKED] = true
1132+ iter[COLUMN_DATA].checked = true
1133+ end
1134+
1135+ wlabel_update()
1136+
1137+ return
1138+ end
1139+
1140+ # def unselect_all_clicked()
1141+ # ------------------------
1142+ # Uncheck all the words in the wordlist treeview
1143+ def unselect_all_clicked()
1144+ @view.model.each do |model, path, iter|
1145+ iter[COLUMN_CHECKED] = false
1146+ iter[COLUMN_DATA].checked = false
1147+ end
1148+
1149+ wlabel_update()
1150+
1151+ return
1152+ end
1153+ end
1154+end
1155addfile ./lib/rflc/ui/flashcard.rb
1156hunk ./lib/rflc/ui/flashcard.rb 1
1157+#
1158+# rflc: ui_flashcard.rb
1159+#
1160+# Flashcard GTK+ UI widget
1161+#
1162+
1163+require 'pango'
1164+require 'gtk2'
1165+
1166+require 'rflc/flashcard'
1167+
1168+# class UI_Flashcard
1169+# ------------------
1170+# Flashcard GTK+ widget
1171+#
1172+# public members:
1173+# @vbox The main vbox which holds all the widgets
1174+# @card the card to render
1175+# @side the side of the card to render
1176+# @front the front side of the card (SETTING_KANA, etc. from util.rb)
1177+# private members:
1178+# @area primary GtkDrawingArea widget
1179+module RFLC
1180+ class UI_Flashcard
1181+ FLASHCARD_SIDE_FRONT, FLASHCARD_SIDE_BACK = *(0..2).to_a
1182+
1183+ attr_writer :text
1184+ attr_reader :vbox, :card
1185+
1186+ # def initialize( card )
1187+ # ----------------
1188+ # Create the UI objects, but don't show them yet
1189+ def initialize( card = nil )
1190+ @card = card
1191+ @side = FLASHCARD_SIDE_FRONT
1192+ @front = SETTING_KANJI
1193+
1194+ @fg = Gdk::Color.new( 0, 0, 0 )
1195+ @bg = Gdk::Color.new( 65535, 65535, 65535 )
1196+
1197+ @area = Gtk::DrawingArea.new
1198+ @area.set_size_request( 100, 125 )
1199+ @area.modify_bg( Gtk::STATE_NORMAL, @bg )
1200+ @area.signal_connect( "expose_event" ) { expose_event() }
1201+
1202+ @layout = @area.create_pango_layout()
1203+
1204+ @vbox = Gtk::Frame.new
1205+ @vbox.set_shadow_type( Gtk::SHADOW_ETCHED_IN )
1206+ @vbox.add( @area )
1207+
1208+ return
1209+ end
1210+
1211+ # def show()
1212+ # ----------
1213+ # Shows the UI
1214+ def show()
1215+ @vbox.show_all
1216+
1217+ return
1218+ end
1219+
1220+ # def redraw()
1221+ # ------------
1222+ # Redraws the widget, fires expose_event
1223+ def redraw()
1224+ @area.window.invalidate( Gdk::Rectangle.new(0, 0, \
1225+ @area.allocation.width - 1, @area.allocation.height - 1), true )
1226+ @area.window.process_updates( true )
1227+
1228+ return
1229+ end
1230+
1231+ # def set_card( card )
1232+ # --------------------
1233+ # set the side of the card
1234+ def set_card( card )
1235+ @card = card
1236+
1237+ return
1238+ end
1239+
1240+ # def set_side( side )
1241+ # --------------------
1242+ # set the side of the card
1243+ def set_side( side )
1244+ @side = side
1245+
1246+ return
1247+ end
1248+
1249+ # def set_front( front )
1250+ # ----------------------
1251+ # set the side of the card
1252+ def set_front( front )
1253+ @front = front
1254+
1255+ return
1256+ end
1257+
1258+ # def flip()
1259+ # ----------
1260+ # Flip the card
1261+ def flip()
1262+ @side ^= 1
1263+
1264+ return
1265+ end
1266+
1267+ # --- Callbacks ---------------------------------------------------------
1268+
1269+ # def expose_event()
1270+ # ------------------
1271+ # redraw event - all the rendering happens here
1272+ def expose_event()
1273+ @gc = @area.style.fg_gc( @area.state )
1274+
1275+ case @side
1276+ when FLASHCARD_SIDE_FRONT
1277+ case @front
1278+ when SETTING_KANA
1279+ text = @card.kana
1280+ when SETTING_KANJI
1281+ text = @card.kanji
1282+ when SETTING_ENGLISH
1283+ text = @card.meanings.join( ", " )
1284+ end
1285+
1286+ # calculate values
1287+ # FIXME: fix calculating `size' plzkthx
1288+ size = @area.allocation.width / text.length
1289+ @layout.set_markup("<span font_desc=\"#{size}\">#{text}</span>")
1290+
1291+ x = (@area.allocation.width / 2) - (@layout.pixel_size[0] / 2)
1292+ y = (@area.allocation.height / 2) - (@layout.pixel_size[1] / 2)
1293+
1294+ when FLASHCARD_SIDE_BACK
1295+ text = "ã‹ãª: #{@card.kana}\n"
1296+ text += "æ¼¢å—: #{@card.kanji}\n"
1297+ text += "English: #{@card.meanings.join(", ")}\n"
1298+
1299+ size = @area.allocation.width / text.length * 3
1300+
1301+ @layout.set_markup("<b><span font_desc=\"#{size}\">#{text}</span></b>")
1302+
1303+ x = (@area.allocation.width / 2) - (@layout.pixel_size[0] / 2)
1304+ y = (@area.allocation.height / 2) - (@layout.pixel_size[1] / 2)
1305+ end
1306+
1307+ @area.window.draw_layout( @gc, x, y, @layout, @fg, @bg )
1308+
1309+ return
1310+ end
1311+ end
1312+end
1313addfile ./lib/rflc/ui/select_deck.rb
1314hunk ./lib/rflc/ui/select_deck.rb 1
1315+#
1316+# rflc: ui/select_deck.rb
1317+#
1318+# User Interface, Select deck view
1319+#
1320+
1321+require 'gtk2'
1322+
1323+require 'rflc/ui/deck_practice'
1324+
1325+# class UI_Select_Deck
1326+# --------------------
1327+# Select deck view
1328+#
1329+# public members:
1330+# @vbox The main vbox which holds all the widgets
1331+# private members:
1332+module RFLC
1333+class UI_Select_Deck
1334+ attr_reader :vbox
1335+
1336+ # def initialize()
1337+ # ----------------
1338+ # Create the UI objects, but don't show them yet
1339+ def initialize()
1340+ # table box container
1341+ table = Gtk::Table.new( 2, 2 )
1342+ table.set_homogeneous( true )
1343+ table.set_column_spacings( 5 )
1344+ table.set_row_spacings( 5 )
1345+
1346+ # bottom bar
1347+ pages = (RFLC::CONFIG.count? / 4.0).ceil
1348+ label = Gtk::Label.new( "Decks (page 1/" + pages.to_s + ")" )
1349+
1350+ quit = Gtk::Button.new( Gtk::Stock::QUIT )
1351+ quit.set_relief( Gtk::RELIEF_NONE )
1352+ quit.signal_connect( "clicked" ) { Gtk.main_quit }
1353+
1354+ back = Gtk::Button.new( Gtk::Stock::GO_BACK )
1355+ back.set_relief( Gtk::RELIEF_NONE )
1356+ back.set_sensitive( false ) # we're on page one by default,
1357+ # so gray out the back button.
1358+
1359+ forward = Gtk::Button.new( Gtk::Stock::GO_FORWARD )
1360+ forward.set_relief( Gtk::RELIEF_NONE )
1361+ if pages == 1
1362+ # if only one page, disable the forward button
1363+ forward.set_sensitive( false )
1364+ end
1365+
1366+ bar = Gtk::HBox.new
1367+ bar.pack_start( quit, false, false, 0 )
1368+ bar.pack_start( label, true, true, 0 )
1369+ bar.pack_start( back, false, false, 0 )
1370+ bar.pack_start( forward, false, false, 0 )
1371+
1372+ # deck view
1373+ count = 0
1374+ for j in 0..1
1375+ for i in 0..1
1376+ # attach a frame
1377+ frame = Gtk::Frame.new
1378+ frame.set_shadow_type( Gtk::SHADOW_ETCHED_IN )
1379+ table.attach( frame, i, i + 1, j, j + 1, \
1380+ Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL )
1381+
1382+ deck = RFLC::CONFIG.decks[count]
1383+
1384+ if deck == nil
1385+ # create a new deck button
1386+ widget = Gtk::Button.new( "Create a new deck" )
1387+ widget.set_image( Gtk::Image.new(Gtk::Stock::NEW,
1388+ Gtk::IconSize::BUTTON) )
1389+ widget.set_relief( Gtk::RELIEF_NONE )
1390+ else
1391+ # deck info view
1392+ label = Gtk::Label.new
1393+ label.set_markup( "<span size=\"xx-large\">#{deck.name}</span>" )
1394+
1395+ description = Gtk::Label.new( deck.description )
1396+ description.set_wrap( true )
1397+
1398+ separator = Gtk::HSeparator.new
1399+
1400+ # hbox
1401+ statistics = Gtk::Label.new
1402+ statistics.set_markup( "Cards: <b>#{deck.count?}</b> | Success rate: <b>87.4%</b>" )
1403+
1404+ practice = Gtk::Button.new( "Practice" )
1405+ practice.set_image( Gtk::Image.new(Gtk::Stock::JUMP_TO,
1406+ Gtk::IconSize::BUTTON) )
1407+ practice.set_relief( Gtk::RELIEF_NONE )
1408+ practice.signal_connect( "clicked", deck ) do |w, deck|
1409+ practice_clicked( deck )
1410+ end
1411+
1412+ hbox = Gtk::HBox.new
1413+ hbox.pack_start( statistics, true, true, 0 )
1414+ hbox.pack_start( practice, false, true, 0 )
1415+
1416+ # pack
1417+ widget = Gtk::VBox.new
1418+ widget.pack_start( label, false, true, 5 )
1419+ widget.pack_start( description, true, true, 0 )
1420+ widget.pack_start( separator, false, false, 0 )
1421+ widget.pack_start( hbox, false, true, 5 )
1422+ end
1423+
1424+ widget.set_border_width( 5 )
1425+ frame.add( widget )
1426+
1427+ count += 1
1428+ end
1429+ end
1430+
1431+ # the main vbox
1432+ @vbox = Gtk::VBox.new
1433+ @vbox.pack_start( table, true, true, 5 )
1434+ @vbox.pack_start( bar, false, true, 0 )
1435+ @vbox.set_border_width( 5 )
1436+
1437+ return
1438+ end
1439+
1440+ # def show()
1441+ # ----------
1442+ # Shows the UI
1443+ def show()
1444+ @vbox.show_all
1445+
1446+ return
1447+ end
1448+
1449+ # --- Callbacks ---------------------------------------------------------
1450+
1451+ # def practice_clicked( w )
1452+ # -------------------------
1453+ # Fired when the "practice" button is clicked. Replace the current view
1454+ # with practice view.
1455+ #
1456+ # deck the deck whose practice button was clicked
1457+ def practice_clicked( deck )
1458+ deck_practice = RFLC::UI_Deck_Practice.new( deck )
1459+ deck_practice.show
1460+
1461+ RFLC::Ui.view.remove( self.vbox )
1462+ RFLC::Ui.view.add( deck_practice.vbox )
1463+
1464+ return
1465+ end
1466+end
1467+end
1468addfile ./lib/rflc/ui/start.rb
1469hunk ./lib/rflc/ui/start.rb 1
1470+#
1471+# rflc: ui/start.rb
1472+#
1473+# User Interface, the practicing window
1474+#
1475+
1476+require 'gtk2'
1477+
1478+require 'rflc/flashcard'
1479+require 'rflc/util'
1480+require 'rflc/ui/deck_practice'
1481+
1482+# class UI_Start
1483+# --------------
1484+# Main class for the User Interface
1485+#
1486+# public members:
1487+# @vbox The main vbox which holds all the widgets
1488+# private members:
1489+# @deck the deck whose practice window this is
1490+# @cards an array, stripped down deck with only cards that are checked
1491+#
1492+# @card the main widget, RFLC::UI_Flashcard
1493+# @id the number of flashcard we're currently at
1494+#
1495+# @label the "Flashcard x/y" label
1496+# @count Number of the card currently visible
1497+module RFLC
1498+ class UI_Start
1499+ attr_reader :vbox
1500+
1501+ # def initialize()
1502+ # ----------------
1503+ # Create the UI objects, but don't show them yet
1504+ def initialize( deck, settings )
1505+ @deck = deck
1506+ @settings = settings
1507+
1508+ @count = @id = 1
1509+
1510+ @cards = Array.new
1511+ i = 0
1512+ @deck.each do |c|
1513+ if c.checked == true
1514+ @cards[i] = c
1515+ i += 1
1516+ end
1517+ end
1518+
1519+ # shuffle
1520+ if @settings[SETTING_SHUFFLE] == true
1521+ @cards.shuffle
1522+ end
1523+
1524+ # flashcard view
1525+ @card = RFLC::UI_Flashcard.new
1526+
1527+ # bottom bar
1528+ close = Gtk::Button.new( Gtk::Stock::CLOSE )
1529+ close.set_relief( Gtk::RELIEF_NONE )
1530+ close.signal_connect( "clicked" ) { close_clicked() }
1531+
1532+ edit = Gtk::Button.new( Gtk::Stock::EDIT )
1533+ edit.set_relief( Gtk::RELIEF_NONE )
1534+
1535+ @flabel = Gtk::Label.new( "" )
1536+ flabel_update()
1537+
1538+ @previous = Gtk::Button.new( "Previous" )
1539+ @previous.set_image( Gtk::Image.new(Gtk::Stock::GO_BACK,
1540+ Gtk::IconSize::BUTTON) )
1541+ @previous.set_relief( Gtk::RELIEF_NONE )
1542+ @previous.signal_connect( "clicked" ) { previous_clicked() }
1543+ @previous.set_sensitive( false )
1544+
1545+ @nextb = Gtk::Button.new( "Next" )
1546+ @nextb.set_image( Gtk::Image.new(Gtk::Stock::GO_FORWARD,
1547+ Gtk::IconSize::BUTTON) )
1548+ @nextb.set_relief( Gtk::RELIEF_NONE )
1549+ @nextb.signal_connect( "clicked" ) { next_clicked() }
1550+ @nextb.set_sensitive( false )
1551+
1552+ @check = Gtk::Button.new( "Check" )
1553+ @check.set_image( Gtk::Image.new(Gtk::Stock::JUMP_TO,
1554+ Gtk::IconSize::BUTTON) )
1555+ @check.set_relief( Gtk::RELIEF_NONE )
1556+ @check.signal_connect( "clicked" ) { check_clicked() }
1557+
1558+ bar = Gtk::HBox.new
1559+ bar.pack_start( close, false, false, 0 )
1560+ bar.pack_start( edit, false, false, 0 )
1561+
1562+ bar.pack_start( @flabel, true, false, 0 )
1563+
1564+ bar.pack_start( @previous, false, false, 0 )
1565+ bar.pack_start( @nextb, false, false, 0 )
1566+ bar.pack_start( @check, false, false, 0 )
1567+
1568+ # the main vbox
1569+ @vbox = Gtk::VBox.new
1570+ @vbox.pack_start( @card.vbox, true, true, 2 )
1571+ @vbox.pack_start( bar, false, true, 0 )
1572+ @vbox.set_border_width( 5 )
1573+
1574+ return
1575+ end
1576+
1577+ # def flabel_update()
1578+ # -------------------
1579+ # update the "Flashcard x/y" label and the shown flashcard
1580+ def flabel_update()
1581+ @flabel.set_text( "Flashcard #{@count}/#{@cards.length}" )
1582+
1583+ @card.set_card( @cards[@count - 1] )
1584+ @card.set_front( @settings[SETTINGS_FRONT] )
1585+
1586+ # don't redraw on the first time, otherwise we'll get a segfault
1587+ # or the kind, since the flashcard isn't realized yet
1588+ if @vbox != nil
1589+ @card.redraw
1590+ end
1591+
1592+ return
1593+ end
1594+
1595+ # def show()
1596+ # ----------
1597+ # Shows the UI
1598+ def show()
1599+ @vbox.show_all
1600+
1601+ return
1602+ end
1603+
1604+ # --- Callbacks ---------------------------------------------------------
1605+ #
1606+ # def close_clicked()
1607+ # ------------------
1608+ # Close button clicked. Show Deck options view.
1609+ def close_clicked()
1610+ deck_practice = RFLC::UI_Deck_Practice.new( @deck )
1611+ deck_practice.show
1612+
1613+ RFLC::Ui.view.remove( self.vbox )
1614+ RFLC::Ui.view.add( deck_practice.vbox )
1615+
1616+ return
1617+ end
1618+
1619+ # def check_clicked()
1620+ # -------------------
1621+ # Check button clicked. Show the answer, flip the card
1622+ def check_clicked()
1623+ @card.set_side( FLASHCARD_SIDE_BACK )
1624+ @card.redraw
1625+ @id += 1
1626+
1627+ @check.set_sensitive( false )
1628+ # if (@id - 1) != 1
1629+ # @previous.set_sensitive( true )
1630+ # end
1631+
1632+ if (@id - 1) != @cards.length
1633+ @nextb.set_sensitive( true )
1634+ end
1635+
1636+ return
1637+ end
1638+
1639+ # def previous_clicked()
1640+ # ------------------
1641+ # show the previous flashcard
1642+ def previous_clicked()
1643+ @count -= 1
1644+
1645+ if @count <= 1
1646+ @count = 1
1647+ @previous.set_sensitive( false )
1648+ end
1649+
1650+ if @count < @id
1651+ @nextb.set_sensitive( true )
1652+ @card.set_side( FLASHCARD_SIDE_BACK )
1653+ @check.set_sensitive( false )
1654+ end
1655+
1656+ flabel_update()
1657+
1658+ return
1659+ end
1660+
1661+ # def next_clicked()
1662+ # ------------------
1663+ # show the next flashcard
1664+ def next_clicked()
1665+ @count += 1
1666+
1667+ @previous.set_sensitive( true )
1668+
1669+ if @count == @id
1670+ @nextb.set_sensitive( false )
1671+ @check.set_sensitive( true )
1672+ @card.set_side( FLASHCARD_SIDE_FRONT )
1673+ end
1674+
1675+ if @count >= @cards.length
1676+ @count = @cards.length
1677+ @nextb.set_sensitive( false )
1678+ end
1679+
1680+ flabel_update()
1681+
1682+ return
1683+ end
1684+ end
1685+end
1686hunk ./lib/rflc/ui_deck_practice.rb 1
1687-#
1688-# rflc: ui_deck_practice.rb
1689-#
1690-# User Interface, Practice (deck options)
1691-#
1692-
1693-require 'check.rb'
1694-
1695-require 'gtk2'
1696-
1697-require 'flashcard.rb'
1698-require 'ui_flashcard.rb'
1699-require 'ui_start.rb'
1700-require 'util.rb'
1701-
1702-# class UI_Deck_Practice
1703-# ----------------------
1704-# Main class for the User Interface
1705-#
1706-# public members:
1707-# @vbox The main vbox which holds all the widgets
1708-# private members:
1709-# @deck the deck whose practice window this is
1710-# @view the treeview wordlist
1711-#
1712-# @wlabel the word count label
1713-class RFLC_UI_Deck_Practice
1714- attr_reader :vbox
1715-
1716- # column indentifiers to make life easier
1717- COLUMN_CHECKED, COLUMN_KANA, COLUMN_KANJI, \
1718- COLUMN_ENGLISH, COLUMN_DATA = *(0..5).to_a
1719-
1720- # def initialize()
1721- # ----------------
1722- # Create the UI objects, but don't show them yet
1723- def initialize( deck )
1724- @deck = deck
1725- @settings = Array.new
1726-
1727- @settings[SETTINGS_FRONT] = 0
1728-
1729- # header
1730- header = Gtk::Label.new
1731- header.set_markup( "<span size=\"xx-large\">#{@deck.name}</span>" )
1732-
1733- # left side
1734-
1735- description = Gtk::Label.new( @deck.description )
1736- description.set_wrap( true )
1737-
1738- # flashcard view
1739- flcard = RFLC_Flashcard.new
1740- flcard.kana = "れã„"
1741- flcard.kanji = "例"
1742- flcard.add_meaning( "Example" )
1743- card = RFLC_UI_Flashcard.new( flcard )
1744- card.set_side( FLASHCARD_SIDE_FRONT )
1745- card.set_front( SETTING_KANA )
1746-
1747- # card front
1748- vbox = Gtk::VBox.new
1749- radio_front = Gtk::RadioButton.new( "Show the word in ã‹ãª" )
1750- radio_front.signal_connect( "toggled", card ) do |w, card|
1751- if w.active?
1752- card.set_front( SETTING_KANA )
1753- card.redraw()
1754-
1755- @settings[SETTINGS_FRONT] = SETTING_KANA
1756- end
1757- end
1758- vbox.pack_start( radio_front, false, true, 0 )
1759-
1760- radio_front = Gtk::RadioButton.new( radio_front, "Show the word in æ¼¢å—" )
1761- radio_front.signal_connect( "toggled", card ) do |w, card|
1762- if w.active?
1763- card.set_front( SETTING_KANJI )
1764- card.redraw()
1765-
1766- @settings[SETTINGS_FRONT] = SETTING_KANJI
1767- end
1768- end
1769- vbox.pack_start( radio_front, false, true, 0 )
1770-
1771- radio_front = Gtk::RadioButton.new( radio_front, "Show the English meaning" )
1772- radio_front.signal_connect( "toggled", card ) do |w, card|
1773- if w.active?
1774- card.set_front( SETTING_ENGLISH )
1775- card.redraw()
1776-
1777- @settings[SETTINGS_FRONT] = SETTING_ENGLISH
1778- end
1779- end
1780- vbox.pack_start( radio_front, false, true, 0 )
1781-
1782- alignment = Gtk::Alignment.new( 0, 0, 0, 0 )
1783- alignment.set_padding( 0, 0, 10, 0 )
1784- alignment.add( vbox )
1785-
1786- front_side = Gtk::Frame.new( "<b>Flashcard front side</b>" )
1787- front_side.label_widget.set_use_markup( true )
1788- front_side.add( alignment )
1789- front_side.set_shadow_type( Gtk::SHADOW_NONE )
1790-
1791- # options
1792- vbox = Gtk::VBox.new
1793- check_write = Gtk::CheckButton.new( "Practice writing kanji" )
1794- check_write.signal_connect( "toggled" ) do |w|
1795- if w.active?
1796- @settings[SETTING_WRITE] = true
1797- end
1798- end
1799- vbox.pack_start( check_write, false, true, 0 )
1800-
1801- check_shuffle = Gtk::CheckButton.new( "Shuffle the deck" )
1802- check_shuffle.signal_connect( "toggled" ) do |w|
1803- if w.active?
1804- @settings[SETTING_SHUFFLE] = true
1805- end
1806- end
1807- vbox.pack_start( check_shuffle, false, true, 0 )
1808-
1809- alignment = Gtk::Alignment.new( 0, 0, 0, 0 )
1810- alignment.set_padding( 0, 0, 10, 0 )
1811- alignment.add( vbox )
1812-
1813- options = Gtk::Frame.new( "<b>Options</b>" )
1814- options.label_widget.set_use_markup( true )
1815- options.add( alignment )
1816- options.set_shadow_type( Gtk::SHADOW_NONE )
1817-
1818- vboxl = Gtk::VBox.new
1819- vboxl.pack_start( description, false, true, 5 )
1820- vboxl.pack_start( front_side, false, true, 0 )
1821- vboxl.pack_start( options, false, true, 0 )
1822- vboxl.pack_start( card.vbox, true, true, 0 )
1823-
1824- # right side
1825-
1826- @wlabel = Gtk::Label.new( "" )
1827- wlabel_update()
1828- wordlist = create_wordlist()
1829-
1830- # (un)?select all
1831- select_all = Gtk::Button.new( "Select all" )
1832- select_all.set_relief( Gtk::RELIEF_NONE )
1833- select_all.signal_connect( "clicked" ) { select_all_clicked() }
1834-
1835- unselect_all = Gtk::Button.new( "Deselect all" )
1836- unselect_all.set_relief( Gtk::RELIEF_NONE )
1837- unselect_all.signal_connect( "clicked" ) { unselect_all_clicked() }
1838-
1839- hbox = Gtk::HBox.new
1840- hbox.pack_start( select_all, true, false, 0 )
1841- hbox.pack_start( unselect_all, true, false, 0 )
1842-
1843- vboxr = Gtk::VBox.new
1844- vboxr.pack_start( @wlabel, false, true, 5 )
1845- vboxr.pack_start( wordlist, true, true, 0 )
1846- vboxr.pack_start( hbox, false, true, 0 )
1847-
1848- # hbox
1849- hbox = Gtk::HBox.new
1850- hbox.pack_start( vboxl, false, true, 5 )
1851- hbox.pack_start( vboxr, true, true, 5 )
1852- hbox.set_border_width( 10 )
1853-
1854- # separator
1855- separator = Gtk::HSeparator.new
1856-
1857- # bottom bar
1858- back = Gtk::Button.new( Gtk::Stock::GO_BACK )
1859- back.set_relief( Gtk::RELIEF_NONE )
1860- back.signal_connect( "clicked" ) { back_clicked() }
1861-
1862- edit = Gtk::Button.new( Gtk::Stock::EDIT )
1863- edit.set_relief( Gtk::RELIEF_NONE )
1864-
1865- start = Gtk::Button.new( "Start" )
1866- start.set_image( Gtk::Image.new(Gtk::Stock::JUMP_TO,
1867- Gtk::IconSize::BUTTON) )
1868- start.set_relief( Gtk::RELIEF_NONE )
1869- start.signal_connect( "clicked" ) { start_clicked() }
1870-
1871- bar = Gtk::HBox.new
1872- bar.pack_start( back, true, false, 0 )
1873- bar.pack_start( edit, true, false, 0 )
1874- bar.pack_start( start, true, false, 0 )
1875-
1876- # the main vbox
1877- @vbox = Gtk::VBox.new
1878- @vbox.pack_start( header, false, false, 10 )
1879- @vbox.pack_start( hbox, true, true, 10 )
1880- @vbox.pack_start( separator, false, true, 0 )
1881- @vbox.pack_start( bar, false, true, 5 )
1882-
1883- return
1884- end
1885-
1886- # def create_wordlist()
1887- # ---------------------
1888- # Create the "flashcards to go through" treeview
1889- def create_wordlist()
1890- store = Gtk::TreeStore.new( TrueClass, String, String, String,
1891- RFLC_Flashcard )
1892-
1893- # take the card data
1894- @deck.each do |card|
1895- parent = store.append( nil )
1896- parent[COLUMN_CHECKED] = card.checked
1897- parent[COLUMN_KANA] = card.kana
1898- parent[COLUMN_KANJI] = card.kanji
1899- parent[COLUMN_ENGLISH] = card.meanings.join( ", " )
1900- parent[COLUMN_DATA] = card # not rendered (RFLC_Flashcard)
1901- end
1902-
1903- @view = Gtk::TreeView.new( store )
1904-
1905- renderer = Gtk::CellRendererToggle.new
1906- renderer.signal_connect( "toggled" ) do |cell, path|
1907- word_toggled( @view.model, path )
1908- end
1909- col = Gtk::TreeViewColumn.new( "è¾¼", renderer,
1910- :active => COLUMN_CHECKED )
1911- @view.append_column( col )
1912-
1913- renderer = Gtk::CellRendererText.new
1914- col = Gtk::TreeViewColumn.new( "ã‹ãª", renderer,
1915- :text => COLUMN_KANA )
1916- @view.append_column( col )
1917- col = Gtk::TreeViewColumn.new( "æ¼¢å—", renderer,
1918- :text => COLUMN_KANJI )
1919- @view.append_column( col )
1920- col = Gtk::TreeViewColumn.new( "English meaning", renderer,
1921- :text => COLUMN_ENGLISH )
1922- @view.append_column( col )
1923-
1924- @view.selection.mode = Gtk::SELECTION_SINGLE
1925- @view.set_headers_clickable( true )
1926- @view.set_enable_search( true ) # TODO: make a search function that
1927- # matches kana, kanji and the meaning
1928- @view.set_reorderable( true ) # FIXME: currently you can make
1929- # sublists. Disable this and make
1930- # saving modified decks work
1931-
1932- # scrolled window
1933- scrolled = Gtk::ScrolledWindow.new()
1934- scrolled.add( @view )
1935- scrolled.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC )
1936- scrolled.set_shadow_type( Gtk::SHADOW_ETCHED_IN )
1937-
1938- return scrolled
1939- end
1940-
1941- def wlabel_update()
1942- @wlabel.set_text( "Check the words to go through: " \
1943- + "(#{@deck.ccount?} out of #{@deck.count?})" )
1944-
1945- return
1946- end
1947-
1948- # def show()
1949- # ----------
1950- # Shows the UI
1951- def show()
1952- @vbox.show_all
1953-
1954- return
1955- end
1956-
1957- # --- Callbacks ---------------------------------------------------------
1958- # def back_clicked()
1959- # ------------------
1960- # Back button clicked. Show Select Deck view.
1961- def back_clicked()
1962- select_deck = RFLC_UI_Select_Deck.new
1963- select_deck.show
1964-
1965- $RFLC_Ui.view.remove( self.vbox )
1966- $RFLC_Ui.view.add( select_deck.vbox )
1967-
1968- return
1969- end
1970-
1971- # def start_clicked()
1972- # -------------------
1973- # Start button clicked. Show the practicing view
1974- def start_clicked()
1975- # check that there's >0 cards in the deck checked
1976- if not @deck.ccount? > 0
1977- dialog = Gtk::MessageDialog.new( $RFLC_Ui.window, \
1978- Gtk::Dialog::DESTROY_WITH_PARENT, Gtk::MessageDialog::INFO,
1979- Gtk::MessageDialog::BUTTONS_OK,
1980- "You must select the cards you want to practice." )
1981- dialog.set_title( "RFLC - Card selection" )
1982-
1983- dialog.signal_connect( "response" ) { dialog.destroy }
1984- dialog.show_all
1985-
1986- return
1987- end
1988-
1989- # replace the view
1990- practice = RFLC_UI_Start.new( @deck, @settings )
1991- practice.show
1992-
1993- $RFLC_Ui.view.remove( self.vbox )
1994- $RFLC_Ui.view.add( practice.vbox )
1995-
1996- return
1997- end
1998-
1999- # def word_toggled()
2000- # ------------------
2001- # Button toggled in the treeview
2002- def word_toggled( model, path )
2003- path = Gtk::TreePath.new( path )
2004-
2005- iter = model.get_iter( path )
2006- toggled = iter[COLUMN_CHECKED]
2007- toggled ^= 1
2008- iter[COLUMN_CHECKED] = toggled
2009- iter[COLUMN_DATA].checked = toggled
2010-
2011- wlabel_update()
2012-
2013- return
2014- end
2015-
2016- # def select_all_clicked()
2017- # ------------------------
2018- # Check all the words in the wordlist treeview
2019- def select_all_clicked()
2020- @view.model.each do |model, path, iter|
2021- iter[COLUMN_CHECKED] = true
2022- iter[COLUMN_DATA].checked = true
2023- end
2024-
2025- wlabel_update()
2026-
2027- return
2028- end
2029-
2030- # def unselect_all_clicked()
2031- # ------------------------
2032- # Uncheck all the words in the wordlist treeview
2033- def unselect_all_clicked()
2034- @view.model.each do |model, path, iter|
2035- iter[COLUMN_CHECKED] = false
2036- iter[COLUMN_DATA].checked = false
2037- end
2038-
2039- wlabel_update()
2040-
2041- return
2042- end
2043-end
2044rmfile ./lib/rflc/ui_deck_practice.rb
2045hunk ./lib/rflc/ui_flashcard.rb 1
2046-#
2047-# rflc: ui_flashcard.rb
2048-#
2049-# Flashcard GTK+ UI widget
2050-#
2051-
2052-require 'check.rb'
2053-
2054-require 'pango'
2055-require 'gtk2'
2056-
2057-require 'flashcard.rb'
2058-
2059-FLASHCARD_SIDE_FRONT, FLASHCARD_SIDE_BACK = *(0..2).to_a
2060-
2061-# class UI_Flashcard
2062-# ------------------
2063-# Flashcard GTK+ widget
2064-#
2065-# public members:
2066-# @vbox The main vbox which holds all the widgets
2067-# @card the card to render
2068-# @side the side of the card to render
2069-# @front the front side of the card (SETTING_KANA, etc. from util.rb)
2070-# private members:
2071-# @area primary GtkDrawingArea widget
2072-class RFLC_UI_Flashcard
2073- attr_writer :text
2074- attr_reader :vbox, :card
2075-
2076- # def initialize( card )
2077- # ----------------
2078- # Create the UI objects, but don't show them yet
2079- def initialize( card = nil )
2080- @card = card
2081- @side = FLASHCARD_SIDE_FRONT
2082- @front = SETTING_KANJI
2083-
2084- @fg = Gdk::Color.new( 0, 0, 0 )
2085- @bg = Gdk::Color.new( 65535, 65535, 65535 )
2086-
2087- @area = Gtk::DrawingArea.new
2088- @area.set_size_request( 100, 125 )
2089- @area.modify_bg( Gtk::STATE_NORMAL, @bg )
2090- @area.signal_connect( "expose_event" ) { expose_event() }
2091-
2092- @layout = @area.create_pango_layout()
2093-
2094- @vbox = Gtk::Frame.new
2095- @vbox.set_shadow_type( Gtk::SHADOW_ETCHED_IN )
2096- @vbox.add( @area )
2097-
2098- return
2099- end
2100-
2101- # def show()
2102- # ----------
2103- # Shows the UI
2104- def show()
2105- @vbox.show_all
2106-
2107- return
2108- end
2109-
2110- # def redraw()
2111- # ------------
2112- # Redraws the widget, fires expose_event
2113- def redraw()
2114- @area.window.invalidate( Gdk::Rectangle.new(0, 0, \
2115- @area.allocation.width - 1, @area.allocation.height - 1), true )
2116- @area.window.process_updates( true )
2117-
2118- return
2119- end
2120-
2121- # def set_card( card )
2122- # --------------------
2123- # set the side of the card
2124- def set_card( card )
2125- @card = card
2126-
2127- return
2128- end
2129-
2130- # def set_side( side )
2131- # --------------------
2132- # set the side of the card
2133- def set_side( side )
2134- @side = side
2135-
2136- return
2137- end
2138-
2139- # def set_front( front )
2140- # ----------------------
2141- # set the side of the card
2142- def set_front( front )
2143- @front = front
2144-
2145- return
2146- end
2147-
2148- # def flip()
2149- # ----------
2150- # Flip the card
2151- def flip()
2152- @side ^= 1
2153-
2154- return
2155- end
2156-
2157- # --- Callbacks ---------------------------------------------------------
2158-
2159- # def expose_event()
2160- # ------------------
2161- # redraw event - all the rendering happens here
2162- def expose_event()
2163- @gc = @area.style.fg_gc( @area.state )
2164-
2165- case @side
2166- when FLASHCARD_SIDE_FRONT
2167- case @front
2168- when SETTING_KANA
2169- text = @card.kana
2170- when SETTING_KANJI
2171- text = @card.kanji
2172- when SETTING_ENGLISH
2173- text = @card.meanings.join( ", " )
2174- end
2175-
2176- # calculate values
2177- # FIXME: fix calculating `size' plzkthx
2178- size = @area.allocation.width / text.length
2179- @layout.set_markup("<span font_desc=\"#{size}\">#{text}</span>")
2180-
2181- x = (@area.allocation.width / 2) - (@layout.pixel_size[0] / 2)
2182- y = (@area.allocation.height / 2) - (@layout.pixel_size[1] / 2)
2183-
2184- when FLASHCARD_SIDE_BACK
2185- text = "ã‹ãª: #{@card.kana}\n"
2186- text += "æ¼¢å—: #{@card.kanji}\n"
2187- text += "English: #{@card.meanings.join(", ")}\n"
2188-
2189- size = @area.allocation.width / text.length * 3
2190-
2191- @layout.set_markup("<b><span font_desc=\"#{size}\">#{text}</span></b>")
2192-
2193- x = (@area.allocation.width / 2) - (@layout.pixel_size[0] / 2)
2194- y = (@area.allocation.height / 2) - (@layout.pixel_size[1] / 2)
2195- end
2196-
2197- @area.window.draw_layout( @gc, x, y, @layout, @fg, @bg )
2198-
2199- return
2200- end
2201-
2202-end
2203rmfile ./lib/rflc/ui_flashcard.rb
2204hunk ./lib/rflc/ui_select_deck.rb 1
2205-#
2206-# rflc: ui_select_deck.rb
2207-#
2208-# User Interface, Select deck view
2209-#
2210-
2211-require 'check.rb'
2212-
2213-require 'gtk2'
2214-
2215-require 'ui_deck_practice.rb'
2216-
2217-# class UI_Select_Deck
2218-# --------------------
2219-# Select deck view
2220-#
2221-# public members:
2222-# @vbox The main vbox which holds all the widgets
2223-# private members:
2224-class RFLC_UI_Select_Deck
2225- attr_reader :vbox
2226-
2227- # def initialize()
2228- # ----------------
2229- # Create the UI objects, but don't show them yet
2230- def initialize()
2231- # table box container
2232- table = Gtk::Table.new( 2, 2 )
2233- table.set_homogeneous( true )
2234- table.set_column_spacings( 5 )
2235- table.set_row_spacings( 5 )
2236-
2237- # bottom bar
2238- pages = ($RFLC_Config.count? / 4.0).ceil
2239- label = Gtk::Label.new( "Decks (page 1/" + pages.to_s + ")" )
2240-
2241- quit = Gtk::Button.new( Gtk::Stock::QUIT )
2242- quit.set_relief( Gtk::RELIEF_NONE )
2243- quit.signal_connect( "clicked" ) { Gtk.main_quit }
2244-
2245- back = Gtk::Button.new( Gtk::Stock::GO_BACK )
2246- back.set_relief( Gtk::RELIEF_NONE )
2247- back.set_sensitive( false ) # we're on page one by default,
2248- # so gray out the back button.
2249-
2250- forward = Gtk::Button.new( Gtk::Stock::GO_FORWARD )
2251- forward.set_relief( Gtk::RELIEF_NONE )
2252- if pages == 1
2253- # if only one page, disable the forward button
2254- forward.set_sensitive( false )
2255- end
2256-
2257- bar = Gtk::HBox.new
2258- bar.pack_start( quit, false, false, 0 )
2259- bar.pack_start( label, true, true, 0 )
2260- bar.pack_start( back, false, false, 0 )
2261- bar.pack_start( forward, false, false, 0 )
2262-
2263- # deck view
2264- count = 0
2265- for j in 0..1
2266- for i in 0..1
2267- # attach a frame
2268- frame = Gtk::Frame.new
2269- frame.set_shadow_type( Gtk::SHADOW_ETCHED_IN )
2270- table.attach( frame, i, i + 1, j, j + 1, \
2271- Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL )
2272-
2273- deck = $RFLC_Config.decks[count]
2274-
2275- if deck == nil
2276- # create a new deck button
2277- widget = Gtk::Button.new( "Create a new deck" )
2278- widget.set_image( Gtk::Image.new(Gtk::Stock::NEW,
2279- Gtk::IconSize::BUTTON) )
2280- widget.set_relief( Gtk::RELIEF_NONE )
2281- else
2282- # deck info view
2283- label = Gtk::Label.new
2284- label.set_markup( "<span size=\"xx-large\">#{deck.name}</span>" )
2285-
2286- description = Gtk::Label.new( deck.description )
2287- description.set_wrap( true )
2288-
2289- separator = Gtk::HSeparator.new
2290-
2291- # hbox
2292- statistics = Gtk::Label.new
2293- statistics.set_markup( "Cards: <b>#{deck.count?}</b> | Success rate: <b>87.4%</b>" )
2294-
2295- practice = Gtk::Button.new( "Practice" )
2296- practice.set_image( Gtk::Image.new(Gtk::Stock::JUMP_TO,
2297- Gtk::IconSize::BUTTON) )
2298- practice.set_relief( Gtk::RELIEF_NONE )
2299- practice.signal_connect( "clicked", deck ) do |w, deck|
2300- practice_clicked( deck )
2301- end
2302-
2303- hbox = Gtk::HBox.new
2304- hbox.pack_start( statistics, true, true, 0 )
2305- hbox.pack_start( practice, false, true, 0 )
2306-
2307- # pack
2308- widget = Gtk::VBox.new
2309- widget.pack_start( label, false, true, 5 )
2310- widget.pack_start( description, true, true, 0 )
2311- widget.pack_start( separator, false, false, 0 )
2312- widget.pack_start( hbox, false, true, 5 )
2313- end
2314-
2315- widget.set_border_width( 5 )
2316- frame.add( widget )
2317-
2318- count += 1
2319- end
2320- end
2321-
2322- # the main vbox
2323- @vbox = Gtk::VBox.new
2324- @vbox.pack_start( table, true, true, 5 )
2325- @vbox.pack_start( bar, false, true, 0 )
2326- @vbox.set_border_width( 5 )
2327-
2328- return
2329- end
2330-
2331- # def show()
2332- # ----------
2333- # Shows the UI
2334- def show()
2335- @vbox.show_all
2336-
2337- return
2338- end
2339-
2340- # --- Callbacks ---------------------------------------------------------
2341-
2342- # def practice_clicked( w )
2343- # -------------------------
2344- # Fired when the "practice" button is clicked. Replace the current view
2345- # with practice view.
2346- #
2347- # deck the deck whose practice button was clicked
2348- def practice_clicked( deck )
2349- deck_practice = RFLC_UI_Deck_Practice.new( deck )
2350- deck_practice.show
2351-
2352- $RFLC_Ui.view.remove( self.vbox )
2353- $RFLC_Ui.view.add( deck_practice.vbox )
2354-
2355- return
2356- end
2357-end
2358rmfile ./lib/rflc/ui_select_deck.rb
2359hunk ./lib/rflc/ui_start.rb 1
2360-#
2361-# rflc: ui_start.rb
2362-#
2363-# User Interface, the practicing window
2364-#
2365-
2366-require 'check.rb'
2367-
2368-require 'gtk2'
2369-
2370-require 'flashcard.rb'
2371-require 'util.rb'
2372-require 'ui_deck_practice.rb'
2373-
2374-# class UI_Start
2375-# --------------
2376-# Main class for the User Interface
2377-#
2378-# public members:
2379-# @vbox The main vbox which holds all the widgets
2380-# private members:
2381-# @deck the deck whose practice window this is
2382-# @cards an array, stripped down deck with only cards that are checked
2383-#
2384-# @card the main widget, RFLC_UI_Flashcard
2385-# @id the number of flashcard we're currently at
2386-#
2387-# @label the "Flashcard x/y" label
2388-# @count Number of the card currently visible
2389-class RFLC_UI_Start
2390- attr_reader :vbox
2391-
2392- # def initialize()
2393- # ----------------
2394- # Create the UI objects, but don't show them yet
2395- def initialize( deck, settings )
2396- @deck = deck
2397- @settings = settings
2398-
2399- @count = @id = 1
2400-
2401- @cards = Array.new
2402- i = 0
2403- @deck.each do |c|
2404- if c.checked == true
2405- @cards[i] = c
2406- i += 1
2407- end
2408- end
2409-
2410- # shuffle
2411- if @settings[SETTING_SHUFFLE] == true
2412- @cards.shuffle
2413- end
2414-
2415- # flashcard view
2416- @card = RFLC_UI_Flashcard.new
2417-
2418- # bottom bar
2419- close = Gtk::Button.new( Gtk::Stock::CLOSE )
2420- close.set_relief( Gtk::RELIEF_NONE )
2421- close.signal_connect( "clicked" ) { close_clicked() }
2422-
2423- edit = Gtk::Button.new( Gtk::Stock::EDIT )
2424- edit.set_relief( Gtk::RELIEF_NONE )
2425-
2426- @flabel = Gtk::Label.new( "" )
2427- flabel_update()
2428-
2429- @previous = Gtk::Button.new( "Previous" )
2430- @previous.set_image( Gtk::Image.new(Gtk::Stock::GO_BACK,
2431- Gtk::IconSize::BUTTON) )
2432- @previous.set_relief( Gtk::RELIEF_NONE )
2433- @previous.signal_connect( "clicked" ) { previous_clicked() }
2434- @previous.