« 環境を再構築 | トップページ | 時計をつくる8 »

2010年10月 6日 (水)

時計をつくる7

自分で書いたコードも時間が経つと忘れてしまって、なんでこんな処理しているのだろうか、と一回削除した後に不具合に気づいてもう一度コードを書き直すという事をしてしまった。
やはりちゃんとソースにコメントを入れることは大事だと痛感。記事も解説を少しも書いていなかったので今回はビシッと書いておくことにする。

まず全体的にメソッドや変数名も若干変更して前よりはrubyぽい命名規則にしたつもり。
イベントで呼ばれるメソッドはon_で始まるようにしたり細かい変更。
Structをまとめたり変数名も一部変更。

次にRTC_configを見てみるとFontDataというフォント情報保存用の構造体を作成してそこにデータをストアするようにした。wxrubyではフォントをシリアライズできるメソッドを提供しているはずだがset_native_font_infoが機能していないようでデシリアライズできない。仕方なく自前で保存するようにしている。
また、wxrubyのインスタンスはYAMLでシリアライズがうまくいかない様なのでto_yaml_propertiesでYAMLで出力しないようにしている。
@min_hand.basisはscaleで針の大きさを調整するために使用している。

  1. # Configuration Management
  2. class RTC_config
  3.   attr_accessor :clock_size, :time_text_color, :time_text_pos_offset,
  4.   :circle_offset, :circle_color, :circle_pen_width,
  5.   :hour_hand, :min_hand, :tick_mark_size,
  6.   :stay_on_top, :position, :font, :font_data
  7.  
  8.   # Struct for configuration value
  9.   Color = Struct.new('Color', :r, :g, :b)
  10.   Point = Struct.new('Point', :x, :y)
  11.   Hand  = Struct.new('Hand', :polygon, :pen_color, :pen_width, :brush_color, :basis)
  12.   FontData  = Struct.new('FontData', :color, :size, :name, :style, :weight)
  13.  
  14.   def initialize
  15.     # If configuration file is invalid, set default value as below
  16.     # Clock app default value
  17.     @clock_size ||= 300
  18.     @time_text_color ||= get_Color(Wx::GREEN)
  19.     @time_text_pos_offset ||= Point.new(@clock_size / 2, @clock_size / 2)
  20.     @tick_mark_size ||= 10
  21.     @circle_offset ||= @clock_size / 2
  22.     @circle_color ||= get_Color(Wx::RED)
  23.     @circle_pen_width ||= 3
  24.     @stay_on_top ||= true
  25.     @position ||= Point.new(0,0)
  26.  
  27.     # Hour Hand default value
  28.     @hour_hand ||= Hand.new
  29.     @hour_hand.polygon ||= [ [0, @clock_size / 30], [-5, 0], [0, - @clock_size / 4], [5, 0] ]
  30.     @hour_hand.pen_color ||= Color.new(1, 1, 1)
  31.     @hour_hand.pen_width ||= 1
  32.     @hour_hand.brush_color ||= get_Color(Wx::CYAN)
  33.     @hour_hand.basis ||= @clock_size # for scaling
  34.  
  35.     # Minites Hand default value
  36.     @min_hand ||= Hand.new
  37.     @min_hand.polygon ||= [ [0, @clock_size / 30], [-5, 0], [0, - @clock_size * 2 / 5], [5, 0] ]
  38.     @min_hand.pen_color ||= Color.new(1, 1, 1)
  39.     @min_hand.pen_width ||= 1
  40.     @min_hand.brush_color ||= get_Color(Wx::BLUE)
  41.     @min_hand.basis ||= @clock_size # for scaling
  42.  
  43.     # Font default value
  44.     # Wx::Font.set_native_font_info doesn't work
  45.     # Font info stored to FontData structure
  46.     @font_data ||= FontData.new
  47.     @font_data.color ||= get_Color(Wx::GREEN)
  48.     @font_data.size ||= 18
  49.     @font_data.name ||= ''
  50.     @font_data.style ||= Wx::FONTSTYLE_NORMAL
  51.     @font_data.weight ||= Wx::FONTWEIGHT_NORMAL
  52.     init()
  53.   end
  54.  
  55.   def init
  56.     # initialize Font
  57.     @font = Wx::Font.new
  58.     @font.set_point_size(@font_data.size)
  59.     @font.set_face_name(@font_data.name)
  60.     @font.set_style(@font_data.style)
  61.     @font.set_weight(@font_data.weight)
  62.   end
  63.  
  64.   def get_Color(obj)
  65.     return Color.new(obj.red, obj.green, obj.blue)
  66.   end
  67.  
  68.   def get_Colour(obj)
  69.     return Wx::Colour.new(obj.r, obj.g, obj.b)
  70.   end
  71.  
  72.   def to_yaml_properties
  73.     arr = self.instance_variables
  74.     # Remove Font info from YAML decoded data
  75.     # Avoid to fail creating this object when made from YAML data
  76.     arr.delete(:@font)
  77.     return arr
  78.   end
  79. end
  80.  

そして次はRubyThroughClock。initializeの冒頭でRTC_config.newを何もせず生成している。これをしておかないとYAMLからRTC_configを生成する段階でエラーが出てしまいインスタンスができない。一度RTC_configオブジェクトを認識しておかないとYAMLからは生成できないようである。classの読み込み順序が関連しているかもしれないがよく分からないので回避として実行している。

ダイアログからダイアログを呼び出す、この場合はRTC_OptionDiagからFontDialogを呼ぶことは正常に行われるが、処理後にFontDialogオブジェクトをdestroyするとSegmentation faultになる。closeとすることで回避できた。RTC_OptionDiagをcloseするとやはりエラーとなる。うーん。

時計のサイズに連動して針のサイズも変化するようにしてみた。scaleというそれらしいメソッドを使用してみた。wxrubyのドキュメントだとまったく使い方がわからなかった。他言語で同じ名前のメソッドがあったのでおそらく同じだろうと試してみたら動いた。これもダックタイピングなのだろうか。
今まで画像関係のメソッドやライブラリ等使ったことがなかったのでこの辺りは一般的な知識なのかもしれないがwxrubyだけで使っていくのはシンドイ印象がある。もっと楽できる方法があるのではないだろうか、とおもっている。

  1. class RubyThroughClock < RTC
  2.   attr_accessor :rtc_config
  3.  
  4.   def initialize(parent = nil)
  5.     super()
  6.  
  7.     # ruby need pre-load to make RTC_config objects probably
  8.     # To avoid configuration loading error, make RTC_config object
  9.     RTC_config.new
  10.  
  11.     # Load configuration file
  12.     begin
  13.       File.open(CONFIG_FILENAME,'r') do |f|
  14.         @rtc_config = YAML.load(f)
  15.       end
  16.     rescue => e
  17.       puts 'config err: ', e
  18.       @rtc_config = RTC_config.new
  19.     end
  20.     @rtc_config.init
  21.  
  22.     # Set transparent color
  23.     set_background_colour(Wx::BLACK)
  24.  
  25.     # Create taskbar icon
  26.     @tbicon = RTC_TaskBarIcon.new(self)
  27.  
  28.     @prev_time = Time.now
  29.  
  30.     # Create Buffer Bitmap
  31.     create_Buffer()
  32.  
  33.     # Event handler
  34.     evt_paint(){|event| on_draw_Clock()}
  35.     evt_size(){|event| on_Size(event)}
  36.     evt_close(){|event| on_Close(event)}
  37.     @m_timer = Wx::Timer.new(self)
  38.     evt_timer(@m_timer.get_id()) { |event| on_Timer(event)}
  39.     @m_timer.start(500)
  40.  
  41.     # Frame size
  42.     set_size(Wx::Size.new(@rtc_config.clock_size, @rtc_config.clock_size))
  43.     move(@rtc_config.position.x, @rtc_config.position.y)
  44.   end
  45.  
  46.   def create_Buffer()
  47.     size = get_client_size()
  48.     @img = Wx::Image.new(size.get_width, size.get_height)
  49.     @img.init_alpha
  50.     @buffer = @img.convert_to_bitmap
  51.   end
  52.  
  53.   def draw_Time(gc, dc, time_str, position)
  54.     mt   = gc.get_transform
  55.  
  56.     # Draw the current time
  57.     colour = @rtc_config.get_Colour(@rtc_config.time_text_color)
  58.     dc.set_text_foreground(colour)
  59.     dc.draw_text(time_str, position.x, position.y)
  60.  
  61.     gc.set_transform(mt)
  62.   end
  63.  
  64.   def draw_Hand(gc, hand, radians)
  65.     path = gc.create_path
  66.     mt   = gc.get_transform
  67.  
  68.     # Set Hand Polygon
  69.     hand.polygon.each do |xy|
  70.       path.add_line_to_point(xy[0], xy[1])
  71.     end
  72.     path.close_subpath
  73.  
  74.     # Change the scale
  75.     scale_xy = (@rtc_config.clock_size.to_f / hand.basis.to_f )
  76.     gc.scale(scale_xy, scale_xy)
  77.     # Move Hand
  78.     gc.rotate(radians)
  79.  
  80.     # Pen Setting
  81.     color = hand.pen_color
  82.     colour = Wx::Colour.new(color.r, color.g, color.b)
  83.     gc.set_pen(Wx::Pen.new(colour, hand.pen_width))
  84.  
  85.     # Brush Setting
  86.     color = hand.brush_color
  87.     colour = Wx::Colour.new(color.r, color.g, color.b)
  88.     gc.set_brush(Wx::Brush.new(colour))
  89.  
  90.     # Drawing
  91.     gc.draw_path(path)
  92.  
  93.     gc.set_transform(mt)
  94.   end
  95.  
  96.   def draw_Circle(gc, rtc_cfg)
  97.     path = gc.create_path
  98.     mt   = gc.get_transform
  99.     rotate_agl = Math::PI * 30  / 180
  100.  
  101.     # Font setting
  102.     font = rtc_cfg.font
  103.     colour = rtc_cfg.get_Colour(rtc_cfg.font_data.color)
  104.     gc.set_font(font,colour)
  105.     # Calculate Radius
  106.     radius = rtc_cfg.clock_size - rtc_cfg.circle_offset
  107.     radius_len = radius * 4 / 5 # adjusted length
  108.     # Set Path
  109.     path.add_circle(0, 0, radius_len - font.get_point_size)
  110.     # Pen Setting
  111.     colour = rtc_cfg.get_Colour(rtc_cfg.circle_color)
  112.     pen = (Wx::Pen.new(colour, rtc_cfg.circle_pen_width))
  113.     gc.set_pen(pen)
  114.  
  115.     # Draw Circle
  116.     gc.draw_path(path)
  117.  
  118.     # Offset X Y position
  119.     gc.translate(-font.get_point_size / 2, -font.get_point_size / 2 - 5)
  120.     gc.rotate(Math::PI)
  121.  
  122.     # Set the number of hour
  123.     for hour in 1..12
  124.       gc.rotate(rotate_agl)
  125.       # Drawing the number of hour
  126.       gc.draw_text(hour.to_s, 0, radius_len, Math::PI * (30 * hour + 180)  / 180)
  127.     end
  128.  
  129.     gc.set_transform(mt)
  130.   end
  131.  
  132.   #
  133.   # Event processing
  134.   #
  135.   def on_draw_Clock()
  136.     @buffer.draw do |dc|
  137.       # Create Graphics Context from Memory DC
  138.       gc = Wx::GraphicsContext.create(dc)
  139.       dc.set_background(Wx::TRANSPARENT_BRUSH)
  140.  
  141.       # Clear DC
  142.       dc.clear
  143.  
  144.       # Offset X Y position
  145.       gc.translate(@rtc_config.clock_size / 2, @rtc_config.clock_size / 2)
  146.  
  147.       # Get current time
  148.       time = Time.now
  149.       time_str = "%02d" % time.hour.to_s + ':' + "%02d" % time.min.to_s
  150.  
  151.       # Draw Circle
  152.       draw_Circle(gc, @rtc_config)
  153.  
  154.       # Draw Hour hand
  155.       hour_offset = Math::PI * 6 * (time.min / 12) / 180
  156.       draw_Hand(gc, @rtc_config.hour_hand, Math::PI * ( 30 * (time.hour % 12)) / 180 + hour_offset)
  157.  
  158.       # Draw Min hand
  159.       draw_Hand(gc, @rtc_config.min_hand, Math::PI * ( 6 * time.min ) / 180)
  160.       draw_Time(gc, dc, time_str, @rtc_config.time_text_pos_offset)
  161.     end
  162.  
  163.     # Shape frame
  164.     r = Wx::Region.new(@buffer)
  165.     set_shape(r)
  166.     paint do |dc|
  167.       dc.draw_bitmap(@buffer, 0, 0, true)
  168.     end
  169.   end
  170.  
  171.   def on_Timer(event)
  172.     unless @prev_time.min == Time.now.min
  173.       @prev_time = Time.now
  174.       refresh
  175.     end
  176.   end
  177.  
  178.   def on_Size(event)
  179.     create_Buffer()
  180.     refresh
  181.   end
  182.  
  183.   def on_Close(event)
  184.     File.open(CONFIG_FILENAME,'w') do |f|
  185.       YAML.dump(@rtc_config,f)
  186.     end
  187.     @tbicon.remove_icon
  188.     @tbicon.destroy
  189.     event.skip
  190.   end
  191.  
  192.   def on_showOption(event)
  193.     # Store old configuration
  194.     prev_rtc_config = @rtc_config.to_yaml
  195.  
  196.     opt = RTC_OptionDiag.new(self)
  197.  
  198.     case opt.show_modal
  199.     when Wx::ID_OK # user clicked ok
  200.       @rtc_config.init
  201.     when Wx::ID_APPLY # user clicked apply
  202.       prev_rtc_config = @rtc_config.to_yaml
  203.       @rtc_config.init
  204.       refresh
  205.     when Wx::ID_CANCEL # user clicked cancel or closed the dialog
  206.       @rtc_config = YAML.load(prev_rtc_config)
  207.       @rtc_config.init
  208.       set_size(Wx::Size.new(@rtc_config.clock_size, @rtc_config.clock_size))
  209.     end
  210.     refresh
  211.  
  212.     opt.destroy
  213.     # opt.close
  214.   end
  215.  
  216.   def on_Stay_on_top(event)
  217.     flag = get_window_style_flag
  218.     if event.is_checked
  219.       flag = flag | Wx::STAY_ON_TOP
  220.     else
  221.       flag = flag ^ Wx::STAY_ON_TOP
  222.     end
  223.     set_window_style_flag(flag)
  224.     @rtc_config.stay_on_top = event.is_checked
  225.     refresh
  226.   end
  227.  
  228.   # Move window to Right-Upper posiotion
  229.   def on_move_RU(event)
  230.     rect = Wx::Display.new.get_client_area
  231.     width = get_screen_rect.get_width
  232.     point = rect.get_top_right
  233.     @rtc_config.position.x = point.x - width
  234.     @rtc_config.position.y = point.y
  235.     move(@rtc_config.position.x, @rtc_config.position.y)
  236.   end
  237.  
  238.   # Move window to Right-Bottom posiotion
  239.   def on_move_RB(event)
  240.     rect = Wx::Display.new.get_client_area
  241.     width = get_screen_rect.get_width
  242.     height = get_screen_rect.get_height
  243.     point = rect.get_bottom_right
  244.     @rtc_config.position.x = point.x - width
  245.     @rtc_config.position.y = point.y - height
  246.     move(@rtc_config.position.x, @rtc_config.position.y)
  247.   end
  248.  
  249.   # Move window to Left-Upper posiotion
  250.   def on_move_LU(event)
  251.     rect = Wx::Display.new.get_client_area
  252.     point = rect.get_top_left
  253.     @rtc_config.position.x = point.x
  254.     @rtc_config.position.y = point.y
  255.     move(@rtc_config.position.x, @rtc_config.position.y)
  256.   end
  257.  
  258.   # Move window to Left-Bottom posiotion
  259.   def on_move_LB(event)
  260.     rect = Wx::Display.new.get_client_area
  261.     height = get_screen_rect.get_height
  262.     point = rect.get_bottom_left
  263.     @rtc_config.position.x = point.x
  264.     @rtc_config.position.y = point.y - height
  265.     move(@rtc_config.position.x, @rtc_config.position.y)
  266.   end
  267. end
  268.  

設定変更をおこなうRTC_OptionDiagやRTC_TaskBarIconは前回より特に変わっていない。
テスト用のプロバティ削除と時間表示の位置を変更できるように追加。画面はこんな感じ。

1

2

RTC_TaskBarIconにあるWx::ID_HIGHESTについて書いておくと
これは予約分のIDの上限値らしい。なので手動で追加する場合はこれを参照しておけば他とぶつからないはず。

  1. # Option Dialog called by Task bar icon
  2. class RTC_OptionDiag < RTC_Option
  3.   def initialize(frame)
  4.     super()
  5.     @frame = frame
  6.     @rtc_config = frame.rtc_config
  7.  
  8.     # Set value from configuration
  9.     stay_on_top.set_value(@rtc_config.stay_on_top)
  10.     clock_size_sldr.set_value(@rtc_config.clock_size)
  11.     circle_offset_sldr.set_value(@rtc_config.circle_offset)
  12.     circle_offset_sldr.set_range(clock_size_sldr.get_min, clock_size_sldr.get_value)
  13.     clock_size_sldr.set_tick_freq(clock_size_sldr.get_max / 10,1)
  14.     circle_offset_sldr.set_tick_freq(circle_offset_sldr.get_max / 10,1)
  15.     fontname.set_value(@rtc_config.font_data.name)
  16.     font_size.set_value(@rtc_config.font_data.size)
  17.     time_pos_x.set_value(@rtc_config.time_text_pos_offset.x)
  18.     time_pos_x.set_range(0, clock_size_sldr.get_value)
  19.     time_pos_y.set_value(@rtc_config.time_text_pos_offset.y)
  20.     time_pos_y.set_range(0, clock_size_sldr.get_value)
  21.  
  22.     # Event handler
  23.     stay_on_top.evt_checkbox(stay_on_top.get_id()){|event| on_Stay_on_top(event)}
  24.     pos_ru.evt_button(pos_ru.get_id()){|event| @frame.on_move_RU(event)}
  25.     pos_lu.evt_button(pos_lu.get_id()){|event| @frame.on_move_LU(event)}
  26.     pos_rb.evt_button(pos_rb.get_id()){|event| @frame.on_move_RB(event)}
  27.     pos_lb.evt_button(pos_lb.get_id()){|event| @frame.on_move_LB(event)}
  28.     clock_size_sldr.evt_slider(clock_size_sldr.get_id()){|event| on_Slider_clock_size()}
  29.     circle_offset_sldr.evt_slider(circle_offset_sldr.get_id()){|event| @rtc_config.circle_offset = circle_offset_sldr.get_value; @frame.refresh}
  30.     font_browse.evt_button(font_browse.get_id()){|event| on_choose_Font(event)}
  31.     font_size.evt_spinctrl(font_size.get_id()){|event| on_change_Fontsize(event)}
  32.     time_pos_x.evt_spinctrl(time_pos_x.get_id()){|event| on_change_TimePosX(event)}
  33.     time_pos_y.evt_spinctrl(time_pos_y.get_id()){|event| on_change_TimePosY(event)}
  34.   end
  35.  
  36.   # Modify Clock Size
  37.   def on_Slider_clock_size()
  38.     size = clock_size_sldr.get_value
  39.     circle_offset_sldr.set_range(clock_size_sldr.get_min, size)
  40.  
  41.     # Change maximum for each related controle
  42.     if circle_offset_sldr.get_max < circle_offset_sldr.get_value
  43.       circle_offset_sldr.set_value(circle_offset_sldr.get_max)
  44.     end
  45.     time_pos_x.set_range(time_pos_x.get_min, size)
  46.     if time_pos_x.get_max < time_pos_x.get_value
  47.       time_pos_x.set_value(time_pos_x.get_max)
  48.     end
  49.     time_pos_y.set_range(time_pos_y.get_min, size)
  50.     if time_pos_y.get_max < time_pos_y.get_value
  51.       time_pos_y.set_value(time_pos_y.get_max)
  52.     end
  53.  
  54.     @rtc_config.clock_size = size
  55.     @frame.set_size(Wx::Size.new(size,size))
  56.   end
  57.  
  58.   def on_Stay_on_top(event)
  59.     # Call method on upper level class
  60.     @frame.on_Stay_on_top(event)
  61.   end
  62.  
  63.   # Font Dialog
  64.   def on_choose_Font(event)
  65.     font = @rtc_config.font
  66.     fontdata = Wx::FontData.new
  67.     fontdata.set_initial_font(font)
  68.     fontdata.set_chosen_font(font)
  69.     colour = @rtc_config.get_Colour(@rtc_config.font_data.color)
  70.     fontdata.set_colour(colour)
  71.  
  72.     fontname.set_value(font.get_face_name)
  73.     font_size.set_value(font.get_point_size)
  74.     fontdiag = Wx::FontDialog.new(self, fontdata);
  75.  
  76.     case fontdiag.show_modal
  77.     when Wx::ID_OK # user clicked ok
  78.       fontdata = fontdiag.get_font_data
  79.       font = fontdata.get_chosen_font
  80.       fontname.set_value(font.get_face_name)
  81.       font_size.set_value(font.get_point_size)
  82.  
  83.       # Store FontData to config
  84.       @rtc_config.font = font
  85.       color =  @rtc_config.get_Color(fontdata.get_colour)
  86.       @rtc_config.font_data.color  = color
  87.       @rtc_config.font_data.size   = font.get_point_size
  88.       @rtc_config.font_data.name   = font.get_face_name
  89.       @rtc_config.font_data.style  = font.get_style
  90.       @rtc_config.font_data.weight = font.get_weight
  91.       @frame.refresh
  92.     when Wx::ID_CANCEL # user clicked cancel or closed the dialog
  93.     end
  94.  
  95.     fontdiag.close
  96.     # fontdiag.destroy
  97.   end
  98.  
  99.   def on_change_Fontsize(event)
  100.     size = event.get_position
  101.     @rtc_config.font.set_point_size(size)
  102.     @rtc_config.font_data.size = size
  103.     @frame.refresh
  104.   end
  105.  
  106.   def on_change_TimePosX(event)
  107.     x = event.get_position
  108.     @rtc_config.time_text_pos_offset.x = x
  109.     @frame.refresh
  110.   end
  111.  
  112.   def on_change_TimePosY(event)
  113.     y = event.get_position
  114.     @rtc_config.time_text_pos_offset.y = y
  115.     @frame.refresh
  116.   end
  117. end
  118.  
  119. # Task bar icon
  120. class RTC_TaskBarIcon < Wx::TaskBarIcon
  121.   # Event ID
  122.   TBMENU_OPTION      = Wx::ID_HIGHEST + 1
  123.   TBMENU_STAY_ON_TOP = Wx::ID_HIGHEST + 2
  124.   TBMENU_MOVE_RU     = Wx::ID_HIGHEST + 3
  125.   TBMENU_MOVE_RB     = Wx::ID_HIGHEST + 4
  126.   TBMENU_MOVE_LU     = Wx::ID_HIGHEST + 5
  127.   TBMENU_MOVE_LB     = Wx::ID_HIGHEST + 6
  128.   TBMENU_EXIT        = Wx::ID_HIGHEST + 7
  129.  
  130.   def initialize(frame)
  131.     super()
  132.     @frame = frame
  133.     @stay_on_top = @frame.rtc_config.stay_on_top
  134.  
  135.     # Icon image
  136.     icon = make_icon('ruby.png')
  137.     set_icon(icon, 'RubyThroughClock')
  138.  
  139.     # Menu Event
  140.     evt_menu(TBMENU_OPTION)      {|event| @frame.on_showOption(event) }
  141.     evt_menu(TBMENU_STAY_ON_TOP) {|event| on_TB_stay_on_top(event) }
  142.     evt_menu(TBMENU_MOVE_RU)     {|event| @frame.on_move_RU(event) }
  143.     evt_menu(TBMENU_MOVE_RB)     {|event| @frame.on_move_RB(event) }
  144.     evt_menu(TBMENU_MOVE_LU)     {|event| @frame.on_move_LU(event) }
  145.     evt_menu(TBMENU_MOVE_LB)     {|event| @frame.on_move_LB(event) }
  146.     evt_menu(TBMENU_EXIT)        {|event| @frame.close }
  147.   end
  148.  
  149.   def on_TB_stay_on_top(event)
  150.     @stay_on_top = event.is_checked
  151.     @frame.on_Stay_on_top(event)
  152.   end
  153.  
  154.   # Make Task bar icon that made from fixed image file
  155.   def make_icon(img_name)
  156.     # Different platforms have different requirements for the
  157.     #  taskbar icon size
  158.     filename = File.join( File.dirname(__FILE__), img_name )
  159.     img = Wx::Image.new(filename, Wx::BITMAP_TYPE_PNG)
  160.     img.set_mask
  161.     if Wx::PLATFORM == "WXMSW"
  162.       img = img.scale(16, 16)
  163.     elsif Wx::PLATFORM == "WXGTK"
  164.       img = img.scale(22, 22)
  165.     end
  166.     # WXMAC can be any size up to 128x128, so don't scale
  167.     icon = Wx::Icon.new
  168.     icon.copy_from_bitmap(Wx::Bitmap.new(img))
  169.     return icon
  170.   end
  171.  
  172.   def create_popup_menu
  173.     # Called by the base class when it needs to popup the menu
  174.     #  (the default evt_right_down event).  Create and return
  175.     #  the menu to display.
  176.     @stay_on_top = @frame.rtc_config.stay_on_top
  177.     menu = Wx::Menu.new
  178.     menu.append(TBMENU_OPTION,     "Option")
  179.     menu.append_check_item(TBMENU_STAY_ON_TOP,"Stay On Top")
  180.     menu.check(TBMENU_STAY_ON_TOP, @stay_on_top)
  181.     submenu = Wx::Menu.new
  182.     submenu.append(TBMENU_MOVE_RU, "Right Upper")
  183.     submenu.append(TBMENU_MOVE_RB, "Right Bottom")
  184.     submenu.append(TBMENU_MOVE_LU, "Left Upper")
  185.     submenu.append(TBMENU_MOVE_LB, "Left Bottom")
  186.     menu.append_menu(Wx::ID_ANY,   "Move",submenu)
  187.     menu.append(TBMENU_EXIT,       "Exit")
  188.     return menu
  189.   end
  190. end
  191.  
  192. class App < Wx::App
  193.   def on_init
  194.     f =  ::RubyThroughClock.new
  195.     f.show
  196.   end
  197. end
  198. App.new.main_loop
  199.  

最後にXRCも晒しておく。忘れていたのはこれくらいかな。

  1. <?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
  2. <resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
  3.   <object class="wxFrame" name="MyFrame1" subclass="RTC">
  4.     <style>wxFRAME_NO_TASKBAR|wxFRAME_SHAPED|wxSTAY_ON_TOP|wxTAB_TRAVERSAL</style>
  5.     <size>500,300</size>
  6.     <title></title>
  7.     <object class="wxBoxSizer">
  8.       <orient>wxHORIZONTAL</orient>
  9.     </object>
  10.   </object>
  11.   <object class="wxDialog" name="MyDialog1" subclass="RTC_Option">
  12.     <style>wxDEFAULT_DIALOG_STYLE</style>
  13.     <size>350,250</size>
  14.     <title>Option</title>
  15.     <object class="wxBoxSizer">
  16.       <orient>wxVERTICAL</orient>
  17.       <object class="sizeritem">
  18.         <option>1</option>
  19.         <flag>wxALL|wxEXPAND</flag>
  20.         <border>5</border>
  21.         <object class="wxNotebook" name="m_notebook1">
  22.           <object class="notebookpage">
  23.             <label>Position</label>
  24.             <selected>0</selected>
  25.             <object class="wxPanel" name="m_panel2">
  26.               <style>wxTAB_TRAVERSAL</style>
  27.               <object class="wxBoxSizer">
  28.                 <orient>wxVERTICAL</orient>
  29.                 <object class="sizeritem">
  30.                   <option>1</option>
  31.                   <flag>wxEXPAND</flag>
  32.                   <border>0</border>
  33.                   <object class="wxGridSizer">
  34.                     <rows>2</rows>
  35.                     <cols>2</cols>
  36.                     <vgap>0</vgap>
  37.                     <hgap>0</hgap>
  38.                     <object class="sizeritem">
  39.                       <option>0</option>
  40.                       <flag>wxALL|wxEXPAND</flag>
  41.                       <border>0</border>
  42.                       <object class="wxButton" name="pos_lu">
  43.                         <label>Left _ Top</label>
  44.                         <default>0</default>
  45.                       </object>
  46.                     </object>
  47.                     <object class="sizeritem">
  48.                       <option>0</option>
  49.                       <flag>wxALL|wxEXPAND</flag>
  50.                       <border>0</border>
  51.                       <object class="wxButton" name="pos_ru">
  52.                         <label>Right _ Top</label>
  53.                         <default>0</default>
  54.                       </object>
  55.                     </object>
  56.                     <object class="sizeritem">
  57.                       <option>0</option>
  58.                       <flag>wxALL|wxEXPAND</flag>
  59.                       <border>0</border>
  60.                       <object class="wxButton" name="pos_lb">
  61.                         <label>Left _ Bottom</label>
  62.                         <default>0</default>
  63.                       </object>
  64.                     </object>
  65.                     <object class="sizeritem">
  66.                       <option>0</option>
  67.                       <flag>wxALL|wxEXPAND</flag>
  68.                       <border>0</border>
  69.                       <object class="wxButton" name="pos_rb">
  70.                         <label>Right _ Bottom</label>
  71.                         <default>0</default>
  72.                       </object>
  73.                     </object>
  74.                   </object>
  75.                 </object>
  76.                 <object class="sizeritem">
  77.                   <option>0</option>
  78.                   <flag>wxALL</flag>
  79.                   <border>5</border>
  80.                   <object class="wxCheckBox" name="stay_on_top">
  81.                     <label>Stay on Top</label>
  82.                     <checked>0</checked>
  83.                   </object>
  84.                 </object>
  85.               </object>
  86.             </object>
  87.           </object>
  88.           <object class="notebookpage">
  89.             <label>Size</label>
  90.             <selected>1</selected>
  91.             <object class="wxPanel" name="m_panel3">
  92.               <style>wxTAB_TRAVERSAL</style>
  93.               <object class="wxBoxSizer">
  94.                 <orient>wxVERTICAL</orient>
  95.                 <object class="sizeritem">
  96.                   <option>1</option>
  97.                   <flag>wxEXPAND</flag>
  98.                   <border>5</border>
  99.                   <object class="wxBoxSizer">
  100.                     <orient>wxHORIZONTAL</orient>
  101.                     <object class="sizeritem">
  102.                       <option>0</option>
  103.                       <flag>wxALL</flag>
  104.                       <border>5</border>
  105.                       <object class="wxStaticText" name="m_staticText3">
  106.                         <label>clock size</label>
  107.                         <wrap>0</wrap>
  108.                       </object>
  109.                     </object>
  110.                     <object class="spacer">
  111.                       <option>1</option>
  112.                       <flag>wxEXPAND</flag>
  113.                       <border>5</border>
  114.                       <size>0,0</size>
  115.                     </object>
  116.                     <object class="sizeritem">
  117.                       <option>0</option>
  118.                       <flag>wxALL</flag>
  119.                       <border>5</border>
  120.                       <object class="wxSlider" name="clock_size_sldr">
  121.                         <style>wxSL_AUTOTICKS|wxSL_HORIZONTAL|wxSL_LABELS</style>
  122.                         <value>100</value>
  123.                         <min>50</min>
  124.                         <max>500</max>
  125.                       </object>
  126.                     </object>
  127.                   </object>
  128.                 </object>
  129.                 <object class="sizeritem">
  130.                   <option>1</option>
  131.                   <flag>wxEXPAND</flag>
  132.                   <border>5</border>
  133.                   <object class="wxBoxSizer">
  134.                     <orient>wxHORIZONTAL</orient>
  135.                     <object class="sizeritem">
  136.                       <option>0</option>
  137.                       <flag>wxALL</flag>
  138.                       <border>5</border>
  139.                       <object class="wxStaticText" name="m_staticText31">
  140.                         <label>circle offset</label>
  141.                         <wrap>0</wrap>
  142.                       </object>
  143.                     </object>
  144.                     <object class="spacer">
  145.                       <option>1</option>
  146.                       <flag>wxEXPAND</flag>
  147.                       <border>5</border>
  148.                       <size>0,0</size>
  149.                     </object>
  150.                     <object class="sizeritem">
  151.                       <option>0</option>
  152.                       <flag>wxALL</flag>
  153.                       <border>5</border>
  154.                       <object class="wxSlider" name="circle_offset_sldr">
  155.                         <style>wxSL_AUTOTICKS|wxSL_HORIZONTAL|wxSL_LABELS</style>
  156.                         <value>100</value>
  157.                         <min>50</min>
  158.                         <max>500</max>
  159.                       </object>
  160.                     </object>
  161.                   </object>
  162.                 </object>
  163.               </object>
  164.             </object>
  165.           </object>
  166.           <object class="notebookpage">
  167.             <label>Font</label>
  168.             <selected>0</selected>
  169.             <object class="wxPanel" name="m_panel4">
  170.               <style>wxTAB_TRAVERSAL</style>
  171.               <object class="wxBoxSizer">
  172.                 <orient>wxVERTICAL</orient>
  173.                 <object class="sizeritem">
  174.                   <option>0</option>
  175.                   <flag>wxEXPAND</flag>
  176.                   <border>5</border>
  177.                   <object class="wxBoxSizer">
  178.                     <orient>wxHORIZONTAL</orient>
  179.                     <object class="sizeritem">
  180.                       <option>0</option>
  181.                       <flag>wxALL</flag>
  182.                       <border>5</border>
  183.                       <object class="wxStaticText" name="m_staticText5">
  184.                         <label>Font</label>
  185.                         <wrap>0</wrap>
  186.                       </object>
  187.                     </object>
  188.                     <object class="sizeritem">
  189.                       <option>1</option>
  190.                       <flag>wxALL</flag>
  191.                       <border>5</border>
  192.                       <object class="wxTextCtrl" name="fontname">
  193.                         <style>wxTE_READONLY</style>
  194.                         <value></value>
  195.                         <maxlength>0</maxlength>
  196.                       </object>
  197.                     </object>
  198.                     <object class="sizeritem">
  199.                       <option>0</option>
  200.                       <flag>wxALL</flag>
  201.                       <border>5</border>
  202.                       <object class="wxButton" name="font_browse">
  203.                         <label>Browse</label>
  204.                         <default>0</default>
  205.                       </object>
  206.                     </object>
  207.                   </object>
  208.                 </object>
  209.                 <object class="sizeritem">
  210.                   <option>1</option>
  211.                   <flag>wxEXPAND</flag>
  212.                   <border>5</border>
  213.                   <object class="wxBoxSizer">
  214.                     <orient>wxHORIZONTAL</orient>
  215.                     <object class="sizeritem">
  216.                       <option>1</option>
  217.                       <flag>wxALL</flag>
  218.                       <border>5</border>
  219.                       <object class="wxStaticText" name="m_staticText6">
  220.                         <label>Font Size</label>
  221.                         <wrap>0</wrap>
  222.                       </object>
  223.                     </object>
  224.                     <object class="sizeritem">
  225.                       <option>0</option>
  226.                       <flag>wxALL</flag>
  227.                       <border>5</border>
  228.                       <object class="wxSpinCtrl" name="font_size">
  229.                         <style>wxSP_ARROW_KEYS</style>
  230.                         <value>1</value>
  231.                         <min>1</min>
  232.                         <max>30</max>
  233.                       </object>
  234.                     </object>
  235.                   </object>
  236.                 </object>
  237.               </object>
  238.             </object>
  239.           </object>
  240.           <object class="notebookpage">
  241.             <label>Time Text</label>
  242.             <selected>0</selected>
  243.             <object class="wxPanel" name="m_panel5">
  244.               <style>wxTAB_TRAVERSAL</style>
  245.               <object class="wxBoxSizer">
  246.                 <orient>wxVERTICAL</orient>
  247.                 <object class="sizeritem">
  248.                   <option>1</option>
  249.                   <flag>wxEXPAND</flag>
  250.                   <border>5</border>
  251.                   <object class="wxBoxSizer">
  252.                     <orient>wxHORIZONTAL</orient>
  253.                     <object class="sizeritem">
  254.                       <option>0</option>
  255.                       <flag>wxALL</flag>
  256.                       <border>5</border>
  257.                       <object class="wxStaticText" name="m_staticText32">
  258.                         <label>&apos;Time&apos; Text Position</label>
  259.                         <wrap>0</wrap>
  260.                       </object>
  261.                     </object>
  262.                     <object class="spacer">
  263.                       <option>1</option>
  264.                       <flag>wxEXPAND</flag>
  265.                       <border>5</border>
  266.                       <size>0,0</size>
  267.                     </object>
  268.                     <object class="sizeritem">
  269.                       <option>1</option>
  270.                       <flag></flag>
  271.                       <border>5</border>
  272.                       <object class="wxBoxSizer">
  273.                         <orient>wxVERTICAL</orient>
  274.                         <object class="sizeritem">
  275.                           <option>1</option>
  276.                           <flag>wxEXPAND</flag>
  277.                           <border>5</border>
  278.                           <object class="wxBoxSizer">
  279.                             <orient>wxHORIZONTAL</orient>
  280.                             <object class="sizeritem">
  281.                               <option>0</option>
  282.                               <flag>wxALL</flag>
  283.                               <border>5</border>
  284.                               <object class="wxStaticText" name="m_staticText12">
  285.                                 <label>x</label>
  286.                                 <wrap>-1</wrap>
  287.                               </object>
  288.                             </object>
  289.                             <object class="sizeritem">
  290.                               <option>0</option>
  291.                               <flag>wxALL</flag>
  292.                               <border>5</border>
  293.                               <object class="wxSpinCtrl" name="time_pos_x">
  294.                                 <style>wxSP_ARROW_KEYS</style>
  295.                                 <value>0</value>
  296.                                 <min>0</min>
  297.                                 <max>999</max>
  298.                               </object>
  299.                             </object>
  300.                           </object>
  301.                         </object>
  302.                         <object class="sizeritem">
  303.                           <option>1</option>
  304.                           <flag>wxEXPAND</flag>
  305.                           <border>5</border>
  306.                           <object class="wxBoxSizer">
  307.                             <orient>wxHORIZONTAL</orient>
  308.                             <object class="sizeritem">
  309.                               <option>0</option>
  310.                               <flag>wxALL</flag>
  311.                               <border>5</border>
  312.                               <object class="wxStaticText" name="m_staticText121">
  313.                                 <label>y</label>
  314.                                 <wrap>-1</wrap>
  315.                               </object>
  316.                             </object>
  317.                             <object class="sizeritem">
  318.                               <option>0</option>
  319.                               <flag>wxALL</flag>
  320.                               <border>5</border>
  321.                               <object class="wxSpinCtrl" name="time_pos_y">
  322.                                 <style>wxSP_ARROW_KEYS</style>
  323.                                 <value>0</value>
  324.                                 <min>0</min>
  325.                                 <max>999</max>
  326.                               </object>
  327.                             </object>
  328.                           </object>
  329.                         </object>
  330.                       </object>
  331.                     </object>
  332.                   </object>
  333.                 </object>
  334.               </object>
  335.             </object>
  336.           </object>
  337.         </object>
  338.       </object>
  339.       <object class="sizeritem">
  340.         <option>0</option>
  341.         <flag>wxEXPAND</flag>
  342.         <border>5</border>
  343.         <object class="wxStdDialogButtonSizer">
  344.           <object class="button">
  345.             <flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
  346.             <border>5</border>
  347.             <object class="wxButton" name="wxID_OK">
  348.               <label>&amp;OK</label>
  349.             </object>
  350.           </object>
  351.           <object class="button">
  352.             <flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
  353.             <border>5</border>
  354.             <object class="wxButton" name="wxID_APPLY">
  355.               <label>&amp;Apply</label>
  356.             </object>
  357.           </object>
  358.           <object class="button">
  359.             <flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
  360.             <border>5</border>
  361.             <object class="wxButton" name="wxID_CANCEL">
  362.               <label>&amp;Cancel</label>
  363.             </object>
  364.           </object>
  365.         </object>
  366.       </object>
  367.     </object>
  368.   </object>
  369. </resource>
  370.  

|

« 環境を再構築 | トップページ | 時計をつくる8 »

時計をつくる」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1201593/37059451

この記事へのトラックバック一覧です: 時計をつくる7:

« 環境を再構築 | トップページ | 時計をつくる8 »