« Twitterクライアントをつくる5 | トップページ | Twitterクライアントをつくる7 »

2011年5月 3日 (火)

Twitterクライアントをつくる6

ほぼ半年ぶりに着手。
忙しすぎる。
既に年末までスケジュールぎっしりらしいので悲しくなる。
久しぶりにコードを読んだがRubyのプログラミング感覚がすっかり失われていてダメだ。
なんとか未完成だったところを潰して基本機能は動くようになりました。

フォロワーやお気に入りのつぶやきを表示できるようにしました。
無駄なAPI浪費があったので整理(最適化して極力APIを使わないようにしたわけではない)
そのおかげで少し表示が早くなった。
その他・・・

勢いでt4rのバージョンを0.6.0に上げてしまった。多分影響ないだろうけど。
それにしても公式RTのメソッドは用意されていないのだろうか。
もしかして気付いて無いだけ?

では、恒例のソース晒し

  1. begin
  2.   require 'rubygems'
  3. rescue LoadError
  4. end
  5. require 'open-uri'
  6. require 'tempfile'
  7.  
  8. require 'wx'
  9. require 'twitter'
  10. require 'watir'
  11.  
  12. require './WTC.rb'
  13.  
  14. # Authentication info file for Oauth
  15. OAUTH_ACCESS_FILE   = File.join( File.dirname(__FILE__), "..", "config", "oauth_access.yml")
  16. OAUTH_CONSUMER_FILE = File.join( File.dirname(__FILE__), "..", "config", "oauth_consumer.yml")
  17.  
  18. # Support class for Follow users info
  19. class FUser
  20.   Follower = Struct.new(:name, :profile_image_url, :description, :following)
  21.   attr_reader :user
  22.   def initialize(name, prof_url, desc, fol)
  23.     @user = Follower.new
  24.     user.name = name
  25.     user.profile_image_url = prof_url
  26.     user.description = desc
  27.     user.following = fol
  28.   end
  29. end
  30.  
  31. class WxrubyTweetClient < WTC
  32.   attr_reader :twit, :friends, :favorites, :my_id
  33.  
  34.   def initialize(parent = nil)
  35.     super()
  36.  
  37.     # Init time line manager
  38.     @tlmgr = Timeline_Manager.new
  39.     add_tab('Home', :friends)
  40.  
  41.     # Event handler
  42.     evt_tool(m_tool_reload) {|event| on_tool_reload}
  43.     evt_tool(m_tool_tweet)  {|event| on_tool_tweet}
  44.     evt_tool(m_tool_group)  {|event| on_tool_group}
  45.     evt_tool(m_tool_search) {|event| on_tool_search}
  46.  
  47.     # Avoid to freeze GUI
  48.     Wx::Timer.every(5) { sleep(0.01) }
  49.  
  50.     @consumer = load_consumer_file()
  51.     login()
  52.  
  53.     # Get friends ids
  54.     begin
  55.       @friends = @twit.graph(:friends)
  56.     rescue
  57.       @friends = []
  58.     end
  59.  
  60.     # Investigate favarites
  61.     @favorites = []
  62.     begin
  63.       favs = @twit.favorites()
  64.       favs.collect do |fr|
  65.         @favorites.push(fr.id)
  66.       end
  67.     rescue
  68.       @favorites = []
  69.     end
  70.  
  71.     # Get my user id
  72.     begin
  73.       timeline = @twit.timeline_for(:user, :count => 1) do |status|
  74.         @my_id = status.user.id
  75.       end
  76.     rescue
  77.       @my_id = 0
  78.     end
  79.  
  80.   end
  81.  
  82.   # Load consumer key/sercret from file
  83.   def load_consumer_file()
  84.     consumer = Hash.new
  85.     if File.exist?(OAUTH_CONSUMER_FILE)
  86.       # Load consumer key/secret file
  87.       begin
  88.         File.open(OAUTH_CONSUMER_FILE,'r') do |f|
  89.           consumer = YAML.load(f)
  90.         end
  91.       rescue => e
  92.         puts 'consumer file load err: ', e, e.backtrace
  93.         exit
  94.       end
  95.     else
  96.       puts "#{OAUTH_CONSUMER_FILE} is not exist", __LINE__
  97.       exit
  98.     end
  99.  
  100.     if consumer["oauth_consumer"].has_key?("key") &&
  101.         consumer["oauth_consumer"].has_key?("secret")
  102.       # Set Consumer key/secret
  103.       Twitter::Client.configure do |conf|
  104.         conf.oauth_consumer_token = consumer["oauth_consumer"]["key"]
  105.         conf.oauth_consumer_secret = consumer["oauth_consumer"]["secret"]
  106.       end
  107.       return consumer
  108.     else
  109.       puts "Consumer key/secret are not exists in #{OAUTH_CONSUMER_FILE}", __LINE__
  110.       exit
  111.     end
  112.   end
  113.  
  114.   # Request access token
  115.   def req_access_token()
  116.     consumer = OAuth::Consumer.new(
  117.         @consumer["oauth_consumer"]["key"],
  118.         @consumer["oauth_consumer"]["secret"],
  119.         :site => 'http://twitter.com'
  120.     )
  121.  
  122.     request_token = consumer.get_request_token
  123.  
  124.     # Launch browser to get PIN code
  125.     begin
  126.       browser = Watir::Browser.new
  127.       browser.goto(request_token.authorize_url)
  128.     rescue => e
  129.       p e, e.backtrace
  130.       puts 'Browser related issue happened'
  131.       exit
  132.     end
  133.  
  134.     oauth_verifier = Wx::get_text_from_user("Input PIN from twitter.com")
  135.     exit if oauth_verifier.empty?
  136.  
  137.     access_token = request_token.get_access_token(
  138.       :oauth_verifier => oauth_verifier
  139.     )
  140.  
  141.     return {"key" => access_token.token, "secret" => access_token.secret}
  142.   end
  143.  
  144.   # Login Twitter.com
  145.   def login()
  146.     if File.exist?(OAUTH_ACCESS_FILE)
  147.       begin
  148.         File.open(OAUTH_ACCESS_FILE,'r') do |f|
  149.           access = YAML.load(f)
  150.           @twit = Twitter::Client.new(access)
  151.         end
  152.       rescue => e
  153.         puts 'oauth_access file load err: ', e, __LINE__
  154.         exit
  155.       end
  156.     else
  157.       begin
  158.         access = Hash.new
  159.         access["oauth_access"] = req_access_token()
  160.         @twit = Twitter::Client.new(access)
  161.         File.open(OAUTH_ACCESS_FILE,'w') do |f|
  162.           YAML.dump(access,f)
  163.         end
  164.       rescue => e
  165.         p e, e.backtrace
  166.         puts 'Oauth err, try again...'
  167.         retry
  168.       end
  169.     end
  170.   end
  171.  
  172.   # Add new TAB to Notebook
  173.   def add_tab(name, type, *key)
  174.     if not @tlmgr.included?(name)
  175.       spanel = Wx::ScrolledWindow.new(m_notebook1, :size => Wx::DEFAULT_SIZE, :style => Wx::VSCROLL)
  176.       spanel.set_scroll_rate(0,15)
  177.       spanel.label = name
  178.       spanel.sizer = @tlmgr.add_tl(name, type, key)
  179.       m_notebook1.add_page(spanel, name)
  180.     end
  181.     return spanel
  182.   end
  183.  
  184.   # Add status to notebook tab
  185.   def add_status(panel, status)
  186.     sizer = Wx::BoxSizer.new(Wx::VERTICAL)
  187.     state_panel = State_panel.new(panel)
  188.     state_panel.update(status, self)
  189.  
  190.     # Get user icon
  191.     icon = Wx::Image.new
  192.     begin
  193.       icon_url = URI.parse(status.user.profile_image_url)
  194.  
  195.       # Get file extname and image type
  196.       tBITMAP_TYPE_GUESS = Wx::Bitmap::BITMAP_TYPE_GUESS
  197.       img_ext = File.extname(icon_url.to_s).downcase
  198.       imgtype = tBITMAP_TYPE_GUESS[img_ext.sub(/^\./, '')]
  199.  
  200.       tf = Tempfile.open(['wtc', img_ext])
  201.       tf.binmode
  202.  
  203.       # Get data from stream to file
  204.       open(icon_url, 'rb') do |i|
  205.         tf.write(i.read(nil))
  206.         tf.close
  207.       end
  208.  
  209.       icon.load_file(tf.path, imgtype)
  210.  
  211.       rescue => e
  212.         begin
  213.           icon.load_file(tf.path, Wx::BITMAP_TYPE_ANY)
  214.         rescue
  215.           icon = Wx::Image.from_bitmap(Wx::NULL_BITMAP)
  216.         end
  217.         p 'error icon ', icon_url
  218.         p e, e.backtrace
  219.     ensure
  220.       tf.close! if not tf.nil?
  221.     end
  222.  
  223.     state_panel.icon.bitmap_label = icon.to_bitmap
  224.  
  225.     # Add status to time line
  226.     sizer.add_item(state_panel, :proportion => 0, :flag => Wx::EXPAND | Wx::ALL)
  227.     @tlmgr.update_sizer(panel.label, sizer)
  228.     panel.fit_inside
  229.   end
  230.  
  231.   # Reload button
  232.   def on_tool_reload
  233.     panel = m_notebook1.page(m_notebook1.get_selection)
  234.     name  = panel.label
  235.     type  = @tlmgr.type(name)
  236.  
  237.     case type
  238.     when :followers
  239.       update_followers(panel, name)
  240.     when :favorites
  241.       update_favorites(panel, name)
  242.     when :search
  243.       update_search(panel, name)
  244.     else
  245.       update_tl(panel, name, type)
  246.     end
  247.     p @twit.account_info.to_hash
  248.   end
  249.  
  250.   def update_tl(panel, name, type)
  251.     sid = @tlmgr.sid(name)
  252.     public_timeline = @twit.timeline_for(type, :since_id => sid, :rpp => 100) do |status|
  253.       add_status(panel, status)
  254.       @tlmgr.update_sid(name, status.id)
  255.     end
  256.   end
  257.  
  258.   def update_favorites(panel, name)
  259.     # Remove exists favorites info
  260.     sizer = @tlmgr.sizer(name)
  261.     sizer.show(false)
  262.     sizer.get_children.collect do |i|
  263.       sizer.remove(0)
  264.     end
  265.     sizer.layout
  266.     sizer.show(true)
  267.  
  268.     # Add favorites
  269.     favs = @twit.favorites()
  270.     favs.collect do |status|
  271.       add_status(panel, status)
  272.       @tlmgr.update_sid(name, status.id)
  273.     end
  274.   end
  275.  
  276.   def update_followers(panel, name)
  277.     # Remove exists follower info
  278.     sizer = @tlmgr.sizer(name)
  279.     sizer.show(false)
  280.     sizer.get_children.collect do |i|
  281.       sizer.remove(0)
  282.     end
  283.     sizer.layout
  284.     sizer.show(true)
  285.  
  286.     # Add followers
  287.     followers = @twit.my(:followers)
  288.  
  289.     followers.collect do |follower|
  290.       status = FUser.new(
  291.               follower.name,
  292.               follower.profile_image_url,
  293.               follower.description,
  294.               follower.following
  295.             )
  296.       add_status(panel, status)
  297.     end
  298.   end
  299.  
  300.   def update_search(panel, name)
  301.     sid = @tlmgr.sid(name)
  302.     key = @tlmgr.key(name)
  303.  
  304.     items = @twit.search(:q => key, :show_user => true, :rpp => 20).each do |status|
  305.       add_status(panel, status)
  306.       @tlmgr.update_sid(name, status.id)
  307.     end
  308.   end
  309.  
  310.   # Tweet button
  311.   def on_tool_tweet
  312.     msg = m_textctrl_tweet.value
  313.     status = @twit.status(:post, msg) if not msg.empty?
  314.     m_textctrl_tweet.clear
  315.   end
  316.  
  317.   # Add tab button
  318.   def on_tool_group
  319.     gd = GroupDialog.new(self)
  320.     gd.show_modal
  321.     gd.destroy
  322.   end
  323.  
  324.   # Search button
  325.   def on_tool_search
  326.     sd = SearchDialog.new(self)
  327.     sd.show_modal
  328.     sd.destroy
  329.   end
  330.  
  331. end
  332.  
  333. class Timeline_Manager
  334.   Data = Struct.new(:sizer, :type, :last_sid, :key)
  335.  
  336.   # def initialize(name)
  337.   def initialize
  338.     @tl_name = Hash.new
  339.   end
  340.  
  341.   def included?(name)
  342.     return @tl_name.include?(name)
  343.   end
  344.  
  345.   def add_tl(name, type, *key)
  346.     @tl_name[name] = Data.new(Wx::BoxSizer.new(Wx::VERTICAL), type, 1, key)
  347.     return @tl_name[name].sizer
  348.   end
  349.  
  350.   # Get sizer for time line
  351.   def sizer(name)
  352.     @tl_name[name].sizer
  353.   end
  354.  
  355.   # Get type/search_key for time line
  356.   def type(name)
  357.     @tl_name[name].type
  358.   end
  359.  
  360.   # Get status id for time line
  361.   def sid(name)
  362.     @tl_name[name].last_sid
  363.   end
  364.  
  365.   # Get search key for time line
  366.   def key(name)
  367.     @tl_name[name].key
  368.   end
  369.  
  370.   # Add new status to TL
  371.   def update_sizer(name, sizer)
  372.     @tl_name[name].sizer.add_item(sizer, :proportion => 0, :flag => Wx::EXPAND | Wx::ALL)
  373.   end
  374.  
  375.   # Update latest status id
  376.   def update_sid(name, id)
  377.     if @tl_name[name].last_sid.nil? or @tl_name[name].last_sid < id
  378.       @tl_name[name].last_sid = id
  379.     end
  380.   end
  381. end
  382.  
  383. class GroupDialog < WTCgroup_dialog
  384.   def initialize(parent = nil)
  385.     super()
  386.     @parent = parent
  387.     # Event handler
  388.     evt_button(m_button_mentions){|event| on_button_mentions}
  389.     evt_button(m_button_rt_of_me){|event| on_button_rt_of_me}
  390.     evt_button(m_button_home){|event| on_button_home}
  391.     evt_button(m_button_rt_by_me){|event| on_button_rt_by_me}
  392.     evt_button(m_button_replies){|event| on_button_replies}
  393.     evt_button(m_button_rt_to_me){|event| on_button_rt_to_me}
  394.     evt_button(m_button_followers){|event| on_button_followers}
  395.     evt_button(m_button_favorates){|event| on_button_favorites}
  396.   end
  397.  
  398.   def on_button_mentions
  399.     @parent.add_tab('Mentions', :mentions)
  400.   end
  401.  
  402.   def on_button_rt_of_me
  403.     @parent.add_tab('RT of Me', :retweetsofme)
  404.   end
  405.  
  406.   def on_button_home
  407.     @parent.add_tab('Home', :friends)
  408.   end
  409.  
  410.   def on_button_rt_by_me
  411.     @parent.add_tab('RT by Me', :retweetsbyme)
  412.   end
  413.  
  414.   def on_button_replies
  415.     @parent.add_tab('Replies', :replies)
  416.   end
  417.  
  418.   def on_button_rt_to_me
  419.     @parent.add_tab('RT to Me', :retweetstome)
  420.   end
  421.  
  422.   def on_button_followers
  423.     @parent.add_tab('Followers', :followers)
  424.   end
  425.  
  426.   def on_button_favorites
  427.     @parent.add_tab('Favorites', :favorites)
  428.   end
  429. end
  430.  
  431. class SearchDialog < WTCsearch_dialog
  432.   def initialize(parent = nil)
  433.     super()
  434.     @parent = parent
  435.     # Event handler
  436.     evt_button(m_button_search){|event| on_button_search}
  437.   end
  438.  
  439.   def on_button_search
  440.     tabname = m_textctrl_search_tabname.value.to_s
  441.     key     = m_textctrl_search_key.value.to_s
  442.  
  443.     if not tabname.empty? and not key.empty?
  444.       @parent.add_tab(tabname, :search, key)
  445.     else
  446.       Wx::message_box('TAB naem or Search key are empty', 'Value Error', Wx::ICON_ERROR)
  447.     end
  448.   end
  449. end
  450.  
  451. class State_panel < WTCpanel
  452.   def initialize(parent = nil)
  453.     super(parent)
  454.     # Event handler
  455.     evt_button(icon){|event| on_button_icon}
  456.     evt_button(m_button_follow){|event| on_button_follow}
  457.     evt_button(m_button_rt){|event| on_button_rt}
  458.     evt_button(m_button_favorite){|event| on_button_favorite}
  459.     evt_button(m_button_reply){|event| on_button_reply}
  460.  
  461.     @frame
  462.     @status
  463.   end
  464.  
  465.   def on_button_icon
  466.     # Launch browser to go user page
  467.     begin
  468.       profile_url = 'http://www.twitter.com/' + @status.user.screen_name
  469.       browser = Watir::Browser.new
  470.       browser.goto(profile_url)
  471.     rescue => e
  472.       p e, e.backtrace
  473.       puts 'Browser related issue happened'
  474.     end
  475.   end
  476.  
  477.   def on_button_follow
  478.     begin
  479.       if m_button_follow.label == 'Follow'
  480.         @frame.twit.friend(:add, @status.user.id)
  481.         m_button_follow.label = 'Unfollow'
  482.         @frame.friends.push(@status.user.id)
  483.         # p 'add friend'
  484.       else
  485.         @frame.twit.friend(:remove, @status.user.id)
  486.         m_button_follow.label = 'Follow'
  487.         @frame.friends.delete(@status.user.id)
  488.         # p 'remove friend'
  489.       end
  490.     rescue
  491.       begin
  492.         @frame.friends = @twit.graph(:friends)
  493.       rescue
  494.         @frame.friends = []
  495.       end
  496.     end
  497.   end
  498.  
  499.   def on_button_rt
  500.   end
  501.  
  502.   def on_button_favorite
  503.     begin
  504.       if m_button_favorite.label == 'Favorite'
  505.         @frame.twit.favorite(:add, @status.id)
  506.         m_button_favorite.label = 'Unfavo..'
  507.         @frame.favorites.push(@status.id)
  508.         # p 'add favorite'
  509.       else
  510.         @frame.twit.favorite(:remove, @status.id)
  511.         m_button_favorite.label = 'Favorite'
  512.         @frame.favorites.delete(@status.id)
  513.         # p 'remove favorite'
  514.       end
  515.     rescue
  516.       begin
  517.         favs = @twit.favorites()
  518.         favs.collect do |fr|
  519.           @frame.favorites.push(fr.id)
  520.         end
  521.       rescue
  522.         @frame.favorites = []
  523.       end
  524.     end
  525.   end
  526.  
  527.   def on_button_reply
  528.     msg = " RT " + @status.text
  529.     @frame.m_textctrl_tweet.value = msg
  530.     @frame.m_textctrl_tweet.set_focus
  531.   end
  532.  
  533.   def update (status, frame)
  534.     @frame = frame
  535.     @status = status
  536.  
  537.     # Follower searching case, 'status' is FUser
  538.     if @status.class.name == "FUser"
  539.       user_name.label = @status.user.name
  540.       tweet.write_text(@status.user.description) if not @status.user.description.nil?
  541.  
  542.       if @status.user.following
  543.         m_button_follow.label = 'Unfollow'
  544.       else
  545.         m_button_follow.label = 'Follow'
  546.       end
  547.       m_button_rt.disable
  548.       m_button_favorite.disable
  549.       m_button_reply.disable
  550.     end
  551.  
  552.     # General case, 'status' is Twitter::Status
  553.     if @status.class.name == "Twitter::Status"
  554.       user_name.label = @status.from_user if not @status.from_user.nil?
  555.       user_name.label = @status.user.name if not @status.user.nil?
  556.       tweet.write_text(@status.text)
  557.  
  558.       friends = @frame.friends
  559.       id = @status.user.id if not @status.user.nil?
  560.       if friends.nil? or not friends.include?(id)
  561.         m_button_follow.label = 'Follow'
  562.       else
  563.         m_button_follow.label = 'Unfollow'
  564.       end
  565.       if id == @frame.my_id
  566.         m_button_follow.disable
  567.       end
  568.  
  569.       favorites = @frame.favorites
  570.       id = @status.id if not status.id.nil?
  571.       if favorites.nil? or not favorites.include?(id)
  572.         m_button_favorite.label = 'Favorite'
  573.       else
  574.         m_button_favorite.label = 'Unfavo..'
  575.       end
  576.     end
  577.   end
  578.  
  579. end
  580.  
  581. class App < Wx::App
  582.   def on_init
  583.     f =  ::WxrubyTweetClient.new
  584.     f.show
  585.   end
  586. end
  587. if not defined?(Ocra)
  588.   App.new.main_loop
  589. end

画面のXML

  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="WTC">
  4.     <style>wxCAPTION|wxCLOSE_BOX|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER|wxSYSTEM_MENU|wxTAB_TRAVERSAL</style>
  5.     <size>500,407</size>
  6.     <title>wxRuby Tweet Client</title>
  7.     <centered>1</centered>
  8.     <object class="wxPanel" name="m_panel4">
  9.       <style>wxTAB_TRAVERSAL</style>
  10.       <object class="wxBoxSizer">
  11.         <orient>wxVERTICAL</orient>
  12.         <object class="sizeritem">
  13.           <option>0</option>
  14.           <flag>wxEXPAND|wxALL</flag>
  15.           <border>5</border>
  16.           <object class="wxBoxSizer">
  17.             <orient>wxVERTICAL</orient>
  18.             <object class="sizeritem">
  19.               <option>0</option>
  20.               <flag>wxEXPAND</flag>
  21.               <border>5</border>
  22.               <object class="wxToolBar" name="m_toolBar1">
  23.                 <style>wxTB_HORIZONTAL</style>
  24.                 <bitmapsize></bitmapsize>
  25.                 <margins></margins>
  26.                 <packing>1</packing>
  27.                 <separation>5</separation>
  28.                 <object class="tool" name="m_tool_reload">
  29.                   <label>tool</label>
  30.                   <tooltip></tooltip>
  31.                   <longhelp></longhelp>
  32.                   <bitmap>../icon/eleganticons/images/Refresh.png</bitmap>
  33.                 </object>
  34.                 <object class="tool" name="m_tool_tweet">
  35.                   <label>Tweet</label>
  36.                   <tooltip>Tweet!</tooltip>
  37.                   <longhelp></longhelp>
  38.                   <bitmap>../icon/eleganticons/images/Speech-Bubble.png</bitmap>
  39.                 </object>
  40.                 <object class="tool" name="m_tool_group">
  41.                   <label>Group</label>
  42.                   <tooltip>Add Tab</tooltip>
  43.                   <longhelp></longhelp>
  44.                   <bitmap>../icon/eleganticons/images/Person-group-add.png</bitmap>
  45.                 </object>
  46.                 <object class="tool" name="m_tool_search">
  47.                   <label>Search</label>
  48.                   <tooltip>Search</tooltip>
  49.                   <longhelp></longhelp>
  50.                   <bitmap>../icon/eleganticons/images/Search.png</bitmap>
  51.                 </object>
  52.                 <object class="tool" name="m_tool_setting">
  53.                   <label>Setting</label>
  54.                   <tooltip>Settings</tooltip>
  55.                   <longhelp></longhelp>
  56.                   <bitmap>../icon/eleganticons/images/Config.png</bitmap>
  57.                 </object>
  58.               </object>
  59.             </object>
  60.           </object>
  61.         </object>
  62.         <object class="sizeritem">
  63.           <option>0</option>
  64.           <flag>wxEXPAND|wxALL</flag>
  65.           <border>5</border>
  66.           <object class="wxBoxSizer">
  67.             <orient>wxVERTICAL</orient>
  68.             <object class="sizeritem">
  69.               <option>0</option>
  70.               <flag>wxEXPAND</flag>
  71.               <border>5</border>
  72.               <object class="wxPanel" name="m_panel1">
  73.                 <style>wxTAB_TRAVERSAL</style>
  74.                 <object class="wxBoxSizer">
  75.                   <orient>wxVERTICAL</orient>
  76.                   <object class="sizeritem">
  77.                     <option>0</option>
  78.                     <flag>wxEXPAND</flag>
  79.                     <border>5</border>
  80.                     <object class="wxTextCtrl" name="m_textCtrl_tweet">
  81.                       <style>wxTE_MULTILINE</style>
  82.                       <value></value>
  83.                       <maxlength>140</maxlength>
  84.                     </object>
  85.                   </object>
  86.                 </object>
  87.               </object>
  88.             </object>
  89.           </object>
  90.         </object>
  91.         <object class="sizeritem">
  92.           <option>1</option>
  93.           <flag>wxALL|wxEXPAND</flag>
  94.           <border>5</border>
  95.           <object class="wxBoxSizer">
  96.             <orient>wxVERTICAL</orient>
  97.             <object class="sizeritem">
  98.               <option>1</option>
  99.               <flag>wxEXPAND</flag>
  100.               <border>5</border>
  101.               <object class="wxNotebook" name="m_notebook1" />
  102.             </object>
  103.           </object>
  104.         </object>
  105.       </object>
  106.     </object>
  107.     <object class="wxStatusBar" name="m_statusBar1">
  108.       <style>wxST_SIZEGRIP</style>
  109.       <fields>1</fields>
  110.     </object>
  111.   </object>
  112.   <object class="wxDialog" name="MyDialog1" subclass="WTCgroup_dialog">
  113.     <style>wxDEFAULT_DIALOG_STYLE</style>
  114.     <title>Add Tab</title>
  115.     <centered>1</centered>
  116.     <object class="wxBoxSizer">
  117.       <orient>wxVERTICAL</orient>
  118.       <object class="sizeritem">
  119.         <option>1</option>
  120.         <flag>wxEXPAND | wxALL</flag>
  121.         <border>5</border>
  122.         <object class="wxListbook" name="m_listbook2">
  123.           <style>wxLB_DEFAULT</style>
  124.           <object class="listbookpage">
  125.             <label>Preset Tab</label>
  126.             <selected>0</selected>
  127.             <object class="wxPanel" name="m_panel5">
  128.               <style>wxTAB_TRAVERSAL</style>
  129.               <object class="wxBoxSizer">
  130.                 <orient>wxVERTICAL</orient>
  131.                 <object class="sizeritem">
  132.                   <option>0</option>
  133.                   <flag>wxEXPAND</flag>
  134.                   <border>5</border>
  135.                   <object class="wxGridSizer">
  136.                     <rows>3</rows>
  137.                     <cols>2</cols>
  138.                     <vgap>0</vgap>
  139.                     <hgap>0</hgap>
  140.                     <object class="sizeritem">
  141.                       <option>0</option>
  142.                       <flag>wxALL|wxEXPAND</flag>
  143.                       <border>5</border>
  144.                       <object class="wxButton" name="m_button_Mentions">
  145.                         <label>Mentions</label>
  146.                         <default>0</default>
  147.                       </object>
  148.                     </object>
  149.                     <object class="sizeritem">
  150.                       <option>0</option>
  151.                       <flag>wxALL|wxEXPAND</flag>
  152.                       <border>5</border>
  153.                       <object class="wxButton" name="m_button_RT_of_me">
  154.                         <label>Retweets of me</label>
  155.                         <default>0</default>
  156.                       </object>
  157.                     </object>
  158.                     <object class="sizeritem">
  159.                       <option>0</option>
  160.                       <flag>wxALL|wxEXPAND</flag>
  161.                       <border>5</border>
  162.                       <object class="wxButton" name="m_button_Home">
  163.                         <label>Home</label>
  164.                         <default>0</default>
  165.                       </object>
  166.                     </object>
  167.                     <object class="sizeritem">
  168.                       <option>0</option>
  169.                       <flag>wxALL|wxEXPAND</flag>
  170.                       <border>5</border>
  171.                       <object class="wxButton" name="m_button_RT_by_me">
  172.                         <label>Retweets by me</label>
  173.                         <default>0</default>
  174.                       </object>
  175.                     </object>
  176.                     <object class="sizeritem">
  177.                       <option>0</option>
  178.                       <flag>wxALL|wxEXPAND</flag>
  179.                       <border>5</border>
  180.                       <object class="wxButton" name="m_button_Replies">
  181.                         <label>Replies</label>
  182.                         <default>0</default>
  183.                       </object>
  184.                     </object>
  185.                     <object class="sizeritem">
  186.                       <option>0</option>
  187.                       <flag>wxALL|wxEXPAND</flag>
  188.                       <border>5</border>
  189.                       <object class="wxButton" name="m_button_RT_to_me">
  190.                         <label>Retweets to me</label>
  191.                         <default>0</default>
  192.                       </object>
  193.                     </object>
  194.                   </object>
  195.                 </object>
  196.                 <object class="sizeritem">
  197.                   <option>0</option>
  198.                   <flag>wxEXPAND</flag>
  199.                   <border>5</border>
  200.                   <object class="wxStaticLine" name="m_staticline1">
  201.                     <style>wxLI_HORIZONTAL</style>
  202.                   </object>
  203.                 </object>
  204.                 <object class="sizeritem">
  205.                   <option>0</option>
  206.                   <flag>wxEXPAND</flag>
  207.                   <border>5</border>
  208.                   <object class="wxGridSizer">
  209.                     <rows>1</rows>
  210.                     <cols>2</cols>
  211.                     <vgap>0</vgap>
  212.                     <hgap>0</hgap>
  213.                     <object class="sizeritem">
  214.                       <option>0</option>
  215.                       <flag>wxALL|wxEXPAND</flag>
  216.                       <border>5</border>
  217.                       <object class="wxButton" name="m_button_Followers">
  218.                         <label>Followers</label>
  219.                         <default>0</default>
  220.                       </object>
  221.                     </object>
  222.                     <object class="sizeritem">
  223.                       <option>0</option>
  224.                       <flag>wxALL|wxEXPAND</flag>
  225.                       <border>5</border>
  226.                       <object class="wxButton" name="m_button_Favorates">
  227.                         <label>Favorates</label>
  228.                         <default>0</default>
  229.                       </object>
  230.                     </object>
  231.                   </object>
  232.                 </object>
  233.               </object>
  234.             </object>
  235.           </object>
  236.         </object>
  237.       </object>
  238.       <object class="sizeritem">
  239.         <option>0</option>
  240.         <flag>wxEXPAND | wxALL</flag>
  241.         <border>5</border>
  242.         <object class="wxStaticLine" name="m_staticline11">
  243.           <style>wxLI_HORIZONTAL</style>
  244.         </object>
  245.       </object>
  246.       <object class="sizeritem">
  247.         <option>0</option>
  248.         <flag>wxALL|wxEXPAND</flag>
  249.         <border>5</border>
  250.         <object class="wxStdDialogButtonSizer">
  251.           <object class="button">
  252.             <flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
  253.             <border>5</border>
  254.             <object class="wxButton" name="wxID_OK">
  255.               <label>&amp;OK</label>
  256.             </object>
  257.           </object>
  258.         </object>
  259.       </object>
  260.     </object>
  261.   </object>
  262.   <object class="wxPanel" name="MyPanel1" subclass="WTCpanel">
  263.     <style>wxTAB_TRAVERSAL</style>
  264.     <object class="wxBoxSizer">
  265.       <orient>wxHORIZONTAL</orient>
  266.       <object class="sizeritem">
  267.         <option>1</option>
  268.         <flag></flag>
  269.         <border>5</border>
  270.         <object class="wxBoxSizer">
  271.           <orient>wxHORIZONTAL</orient>
  272.           <object class="sizeritem">
  273.             <option>0</option>
  274.             <flag></flag>
  275.             <border>5</border>
  276.             <object class="wxBoxSizer">
  277.               <minsize>150,-1</minsize>
  278.               <orient>wxVERTICAL</orient>
  279.               <object class="sizeritem">
  280.                 <option>0</option>
  281.                 <flag>wxALL|wxALIGN_CENTER_HORIZONTAL</flag>
  282.                 <border>5</border>
  283.                 <object class="wxBitmapButton" name="icon">
  284.                   <bitmap />
  285.                   <default>0</default>
  286.                 </object>
  287.               </object>
  288.               <object class="sizeritem">
  289.                 <option>0</option>
  290.                 <flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
  291.                 <border>5</border>
  292.                 <object class="wxStaticText" name="user_name">
  293.                   <label></label>
  294.                   <wrap>-1</wrap>
  295.                 </object>
  296.               </object>
  297.             </object>
  298.           </object>
  299.           <object class="sizeritem">
  300.             <option>1</option>
  301.             <flag>wxEXPAND</flag>
  302.             <border>5</border>
  303.             <object class="wxBoxSizer">
  304.               <orient>wxHORIZONTAL</orient>
  305.               <object class="sizeritem">
  306.                 <option>1</option>
  307.                 <flag>wxALL|wxEXPAND</flag>
  308.                 <border>5</border>
  309.                 <object class="wxTextCtrl" name="tweet">
  310.                   <style>wxTE_MULTILINE</style>
  311.                   <value></value>
  312.                   <maxlength>0</maxlength>
  313.                 </object>
  314.               </object>
  315.             </object>
  316.           </object>
  317.           <object class="sizeritem">
  318.             <option>0</option>
  319.             <flag>wxALL</flag>
  320.             <border>5</border>
  321.             <object class="wxBoxSizer">
  322.               <orient>wxVERTICAL</orient>
  323.               <object class="sizeritem">
  324.                 <option>0</option>
  325.                 <flag>wxEXPAND</flag>
  326.                 <border>5</border>
  327.                 <object class="wxButton" name="m_button_follow">
  328.                   <style>wxBU_EXACTFIT</style>
  329.                   <label>Follow</label>
  330.                   <default>0</default>
  331.                 </object>
  332.               </object>
  333.               <object class="sizeritem">
  334.                 <option>0</option>
  335.                 <flag>wxEXPAND</flag>
  336.                 <border>5</border>
  337.                 <object class="wxButton" name="m_button_rt">
  338.                   <style>wxBU_EXACTFIT</style>
  339.                   <label>RT</label>
  340.                   <default>0</default>
  341.                 </object>
  342.               </object>
  343.               <object class="sizeritem">
  344.                 <option>0</option>
  345.                 <flag>wxEXPAND</flag>
  346.                 <border>5</border>
  347.                 <object class="wxButton" name="m_button_favorite">
  348.                   <style>wxBU_EXACTFIT</style>
  349.                   <label>Favorite</label>
  350.                   <default>0</default>
  351.                 </object>
  352.               </object>
  353.               <object class="sizeritem">
  354.                 <option>0</option>
  355.                 <flag>wxEXPAND</flag>
  356.                 <border>5</border>
  357.                 <object class="wxButton" name="m_button_reply">
  358.                   <style>wxBU_EXACTFIT</style>
  359.                   <label>Reply</label>
  360.                   <default>0</default>
  361.                 </object>
  362.               </object>
  363.             </object>
  364.           </object>
  365.         </object>
  366.       </object>
  367.     </object>
  368.   </object>
  369.   <object class="wxDialog" name="MyDialog2" subclass="WTCsearch_dialog">
  370.     <style>wxDEFAULT_DIALOG_STYLE</style>
  371.     <title>Search</title>
  372.     <centered>1</centered>
  373.     <object class="wxBoxSizer">
  374.       <minsize>200,-1</minsize>
  375.       <orient>wxVERTICAL</orient>
  376.       <object class="sizeritem">
  377.         <option>0</option>
  378.         <flag>wxALL|wxEXPAND</flag>
  379.         <border>5</border>
  380.         <object class="wxPanel" name="m_panel4">
  381.           <style>wxTAB_TRAVERSAL</style>
  382.           <object class="wxBoxSizer">
  383.             <orient>wxVERTICAL</orient>
  384.             <object class="sizeritem">
  385.               <option>0</option>
  386.               <flag>wxEXPAND</flag>
  387.               <border>5</border>
  388.               <object class="wxBoxSizer">
  389.                 <orient>wxVERTICAL</orient>
  390.                 <object class="sizeritem">
  391.                   <option>0</option>
  392.                   <flag>wxALL</flag>
  393.                   <border>5</border>
  394.                   <object class="wxStaticText" name="m_staticText3">
  395.                     <label>TAB name</label>
  396.                     <wrap>-1</wrap>
  397.                   </object>
  398.                 </object>
  399.                 <object class="sizeritem">
  400.                   <option>0</option>
  401.                   <flag>wxALL|wxEXPAND</flag>
  402.                   <border>5</border>
  403.                   <object class="wxTextCtrl" name="m_textCtrl_search_tabname">
  404.                     <value></value>
  405.                     <maxlength>100</maxlength>
  406.                   </object>
  407.                 </object>
  408.               </object>
  409.             </object>
  410.             <object class="sizeritem">
  411.               <option>0</option>
  412.               <flag>wxEXPAND</flag>
  413.               <border>5</border>
  414.               <object class="wxBoxSizer">
  415.                 <orient>wxVERTICAL</orient>
  416.                 <object class="sizeritem">
  417.                   <option>0</option>
  418.                   <flag>wxALL</flag>
  419.                   <border>5</border>
  420.                   <object class="wxStaticText" name="m_staticText2">
  421.                     <label>Input Search Key</label>
  422.                     <wrap>-1</wrap>
  423.                   </object>
  424.                 </object>
  425.                 <object class="sizeritem">
  426.                   <option>1</option>
  427.                   <flag>wxALL|wxEXPAND</flag>
  428.                   <border>5</border>
  429.                   <object class="wxTextCtrl" name="m_textCtrl_search_key">
  430.                     <value></value>
  431.                     <maxlength>0</maxlength>
  432.                   </object>
  433.                 </object>
  434.               </object>
  435.             </object>
  436.             <object class="sizeritem">
  437.               <option>1</option>
  438.               <flag>wxEXPAND</flag>
  439.               <border>5</border>
  440.               <object class="wxBoxSizer">
  441.                 <orient>wxVERTICAL</orient>
  442.                 <object class="sizeritem">
  443.                   <option>0</option>
  444.                   <flag>wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND</flag>
  445.                   <border>5</border>
  446.                   <object class="wxButton" name="m_button_search">
  447.                     <label>Add Tab</label>
  448.                     <default>0</default>
  449.                   </object>
  450.                 </object>
  451.               </object>
  452.             </object>
  453.           </object>
  454.         </object>
  455.       </object>
  456.       <object class="sizeritem">
  457.         <option>0</option>
  458.         <flag>wxEXPAND</flag>
  459.         <border>5</border>
  460.         <object class="wxStaticLine" name="m_staticline2">
  461.           <style>wxLI_HORIZONTAL</style>
  462.         </object>
  463.       </object>
  464.       <object class="sizeritem">
  465.         <option>0</option>
  466.         <flag>wxEXPAND</flag>
  467.         <border>5</border>
  468.         <object class="wxStdDialogButtonSizer">
  469.           <object class="button">
  470.             <flag>wxALIGN_CENTER_HORIZONTAL|wxALL</flag>
  471.             <border>5</border>
  472.             <object class="wxButton" name="wxID_OK">
  473.               <label>&amp;OK</label>
  474.             </object>
  475.           </object>
  476.         </object>
  477.       </object>
  478.     </object>
  479.   </object>
  480. </resource>

|

« Twitterクライアントをつくる5 | トップページ | Twitterクライアントをつくる7 »

Twitterクライアントをつくる」カテゴリの記事

コメント

コメントを書く



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




トラックバック

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

この記事へのトラックバック一覧です: Twitterクライアントをつくる6:

« Twitterクライアントをつくる5 | トップページ | Twitterクライアントをつくる7 »