Skip to content
Browse files

Upgrade to 0.10.X

  • Loading branch information...
1 parent 80ea800 commit 401afa0301b84162e93467f7d80d3e0855fca6b1 @rscottm rscottm committed Dec 17, 2012
Showing with 296 additions and 138 deletions.
  1. +296 −138 assets/demo-scripts/demo-ruboto-irb.rb
View
434 assets/demo-scripts/demo-ruboto-irb.rb
@@ -8,13 +8,17 @@
#
#######################################################
-require 'ruboto'
-require 'ruboto/generate'
-confirm_ruboto_version(10, false)
+require 'ruboto/activity'
+require 'ruboto/widget'
+require 'ruboto/util/stack'
+require 'ruboto/util/toast'
+
+require 'fileutils'
java_import "android.view.WindowManager"
java_import "android.view.Gravity"
java_import "android.view.KeyEvent"
+java_import "android.view.MenuItem"
java_import "android.text.util.Linkify"
java_import "android.app.AlertDialog"
java_import "android.content.DialogInterface"
@@ -23,94 +27,290 @@
ruboto_import_widgets :TabHost, :LinearLayout, :FrameLayout, :TabWidget,
:Button, :EditText, :TextView, :ListView, :ScrollView
-ruboto_generate_widget(android.widget.EditText => "org.ruboto.widget.RubotoEditText")
require 'stringio'
$main_binding = self.instance_eval{binding}
-$activity.start_ruboto_activity("$ruboto_irb") do
- getWindow.setSoftInputMode(
- WindowManager::LayoutParams::SOFT_INPUT_STATE_VISIBLE |
- WindowManager::LayoutParams::SOFT_INPUT_ADJUST_RESIZE)
+################################################################################
+#
+# Java Subclasses
+#
+
+class FlingGestureListener < android.view.GestureDetector::SimpleOnGestureListener
+ def self.context=(context)
+ @@context = context
+ end
+
+ def initialize()
+ @context = @@context.ruboto_java_instance
+ @activity = @@context
+ @scroller = android.widget.Scroller.new(@context)
+ @x = 0
+ super
+ end
+
+ def onDown(e)
+ return false if @scroller.finished?
+ @scroller.forceFinished(true)
+ return true
+ end
+
+ def onFling(e1, e2, velocityX, velocityY)
+ return false if velocityY.abs < android.view.ViewConfiguration.get(@context).getScaledMinimumFlingVelocity
+ @x = @activity.edit_script.scroll_x
+ max = @activity.edit_script.getLayout.height - @activity.edit_script.height + @activity.edit_script.line_height
+ @scroller.fling(0, @activity.edit_script.scroll_y, 0, 0-velocityY, @x, @x, 0, max)
+ @activity.edit_script.post(my_run_proc)
+ return true
+ end
+
+ def my_run_proc
+ @run ||= proc do
+ if not @scroller.finished? and @scroller.compute_scroll_offset
+ @activity.edit_script.scrollTo(@x, @scroller.curr_y)
+ @activity.edit_script.post(my_run_proc)
+ end
+ end
+ end
+end
+
+class LineNumberEditText < android.widget.EditText
+ def initialize(context)
+ super
+ @show_line_numbers = context.getPreferences(Context::MODE_PRIVATE).getBoolean("LineNumbers", true)
+ @paint = android.graphics.Paint.new
+ @paint.color = (text_colors.default_color & android.graphics.Color.argb(0xAA, 0xFF, 0xFF, 0xFF))
+ @paint.text_size = (text_size * 0.6)
+ @paint.setTypeface android.graphics.Typeface::MONOSPACE
+ @text_paint = android.text.TextPaint.new(@paint)
+ @default_left = padding_left
+ @current_magnitude = @line_number_width = 0
+ @lc = 1
+
+ self.hint = "Enter source code here."
+ self.gravity = Gravity::TOP
+ self.horizontally_scrolling = true
+ self.raw_input_type = (android.text.InputType::TYPE_TEXT_FLAG_NO_SUGGESTIONS | android.text.InputType::TYPE_TEXT_FLAG_MULTI_LINE)
+ self.typeface = android.graphics.Typeface::MONOSPACE
+ self.scroll_container = true
+ self.filters = [android.text.InputFilter::LengthFilter.new(1000000)].to_java(android.text.InputFilter)
+ end
+
+ def toggle_show_line_numbers
+ @show_line_numbers = !@show_line_numbers
+ prefs_editor = context.getPreferences(Context::MODE_PRIVATE).edit
+ prefs_editor.putBoolean("LineNumbers", @show_line_numbers)
+ prefs_editor.commit
+ build_line_numbers
+ invalidate
+ end
+
+ def min(a, b)
+ a > b ? b : a
+ end
+
+ def max(a, b)
+ a > b ? a : b
+ end
+
+ def build_line_numbers
+ if @layout.nil?
+ @text = android.text.SpannableStringBuilder.new("1")
+ @layout = android.text.DynamicLayout.new(@text, @text_paint, 200,
+ android.text.Layout::Alignment::ALIGN_RIGHT,
+ 0.0, line_height, false)
+ @line_ascent = @layout.get_line_ascent(0)
+ end
+
+ new_magnitude = (!@show_line_numbers || line_count == 0) ? 0 : ((Math.log10(line_count) + 0.0001).to_i + 1)
+ if @current_magnitude != new_magnitude
+ @line_number_width = new_magnitude * @paint.text_size
+ post{set_padding(@default_left + @line_number_width, padding_top, padding_right, padding_bottom)}
+ @current_magnitude = new_magnitude
+ end
+
+ if @lc > line_count && line_count > 0
+ @text.replace(calculate_line_number_size(line_count), @text.length, "")
+ else
+ (@lc + 1).upto(line_count){|i| @text.append("\n#{i}")}
+ end
+
+ @lc = line_count == 0 ? 1 : line_count
+ end
+
+ def calculate_line_number_size(i)
+ size = (i * 2) - 1
+ 1.upto((Math.log10(i) + 0.0001).to_i){|x| size += i - ((10 ** x) - 1)}
+ size
+ end
+
+ def onDraw(canvas)
+ super
+
+ if (@show_line_numbers && line_count > 0)
+ build_line_numbers if @layout.nil? or @lc != line_count
+
+ canvas.save
+
+ canvas.translate(scroll_x - 200 + @line_number_width, extended_padding_top - @line_ascent)
+ canvas.clipRect(200 - @line_number_width, scroll_y - extended_padding_top, padding_left + 200,
+ bottom - top - extended_padding_bottom + scroll_y - extended_padding_top + @line_ascent)
+ @layout.draw(canvas)
+
+ canvas.restore
+ end
+ end
+end
+
+################################################################################
+
+$irb.start_ruboto_activity("$ruboto_irb") do
+ attr_reader :ruboto_java_instance
#
# UI setup
#
+
+ def on_create(bundle)
+ getWindow.setSoftInputMode(
+ WindowManager::LayoutParams::SOFT_INPUT_STATE_VISIBLE |
+ WindowManager::LayoutParams::SOFT_INPUT_ADJUST_RESIZE)
+
+ super
- setup_content do
@history = [""]
@cursor = 0
- @tabs = TabHost.new(self, nil) # Needs to be created this way to avoid bug introduced Android >= 3.0
- @tab_container = linear_layout(:orientation => :vertical, :height => :fill_parent, :parent => @tabs)
+ @tabs = TabHost.new(@ruboto_java_instance, nil) # Needs to be created this way to avoid bug introduced Android >= 3.0
+ @tab_container = linear_layout(:orientation => :vertical, :height => :fill_parent,
+ :parent => @tabs, :background_color => android.graphics.Color::BLACK)
tab_widget(:id => AndroidIds::tabs, :parent => @tab_container)
frame_layout(:id => AndroidIds::tabcontent, :height => :fill_parent, :parent => @tab_container) do
linear_layout(:id => 55555, :height => :fill_parent, :orientation => :vertical) do
- @irb_edit = edit_text :lines => 1, :on_key_listener => @on_key_listener
- @irb_text = text_view :text => "#{explanation_text}\n\n>> ", :height => :fill_parent,
+ @irb_edit = edit_text(:lines => 1, :on_key_listener => (proc{|v,kc,e| my_key_listener(v,kc,e)}))
+ @irb_text = text_view(:text => "#{explanation_text}\n\n>> ", :height => :fill_parent,
:gravity => (Gravity::BOTTOM | Gravity::CLIP_VERTICAL),
:text_color => android.graphics.Color::WHITE,
- :movement_method => ScrollingMovementMethod.new;
+ :movement_method => ScrollingMovementMethod.new)
end
- linear_layout(:id => 55556, :orientation => :vertical) do
+
+ ll = linear_layout(:id => 55556, :orientation => :vertical) do
@edit_name = edit_text :text => "untitled.rb"
- @edit_script = ruboto_edit_text(:hint => "Enter source code here.", #:text => script_code,
- :gravity => Gravity::TOP, :horizontally_scrolling=> true,
- :raw_input_type => (android.text.InputType::TYPE_TEXT_FLAG_NO_SUGGESTIONS |
- android.text.InputType::TYPE_TEXT_FLAG_MULTI_LINE),
- :typeface => android.graphics.Typeface::MONOSPACE, :scroll_container => true,
- :filters => [android.text.InputFilter::LengthFilter.new(1000000)].to_java(android.text.InputFilter),
- :layout => ({:height= => :fill_parent, :width= => :fill_parent, :weight= => 1}))
end
- @scripts = list_view :id => 55557, :list => [],
- :on_item_click_listener => proc{|av, v, p, i| edit @scripts_list[p]}
+ @edit_script = LineNumberEditText.new(@ruboto_java_instance)
+ ll.addView @edit_script
+ @edit_script.layout_params.height = View.convert_constant(:fill_parent)
+ @edit_script.layout_params.width = View.convert_constant(:fill_parent)
+ @edit_script.layout_params.weight = 1
+
+ @scripts = list_view(:id => 55557, :list => [],
+ :on_item_click_listener => (proc{|av, v, p, i| edit @scripts_list[p]}))
end
- @edit_script.initialize_ruboto_callbacks &@line_number_draw
+ FlingGestureListener.context = self
+ @fling_listener = FlingGestureListener.new
+ @gestureDetector = android.view.GestureDetector.new(@fling_listener)
+ @edit_script.setOnTouchListener do |view, event|
+ @gestureDetector.onTouchEvent(event)
+ end
registerForContextMenu(@scripts)
load_script_list
+
+ @current_tab = "irb"
@tabs.setup
@tabs.addTab(@tabs.newTabSpec("irb").setContent(55555).setIndicator("IRB"))
@tabs.addTab(@tabs.newTabSpec("editor").setContent(55556).setIndicator("Editor"))
@tabs.addTab(@tabs.newTabSpec("scripts").setContent(55557).setIndicator("Scripts"))
- @tabs.setOnTabChangedListener(@on_tab_change_listener)
- @tabs
+ @tabs.setOnTabChangedListener(proc{|t| tab_changed(t)})
+ self.content_view = @tabs
end
-
+
+ def edit_script
+ @edit_script
+ end
+
#
# Menu Items
#
- handle_create_options_menu do |menu|
- add_menu("Save", R::drawable::ic_menu_save) do
- save(@edit_name.getText.toString, @edit_script.getText.toString)
- end
+ def on_create_options_menu(m)
+ super
+
+ mi = m.add("Execute")
+ mi.set_icon R::drawable::ic_menu_slideshow
+ mi.show_as_action = MenuItem::SHOW_AS_ACTION_IF_ROOM if MenuItem.const_defined?("SHOW_AS_ACTION_IF_ROOM")
+
+ mi = m.add("Save")
+ mi.set_icon R::drawable::ic_menu_save
+ mi.show_as_action = MenuItem::SHOW_AS_ACTION_IF_ROOM if MenuItem.const_defined?("SHOW_AS_ACTION_IF_ROOM")
- add_menu("Execute", Ruboto::R::drawable::ic_menu_play) do
+ mi = m.add("New")
+ mi.set_icon R::drawable::ic_menu_add
+ mi.show_as_action = MenuItem::SHOW_AS_ACTION_IF_ROOM if MenuItem.const_defined?("SHOW_AS_ACTION_IF_ROOM")
+
+ mi = m.add("Edit History")
+ mi.set_icon R::drawable::ic_menu_recent_history
+
+ mi = m.add("Toggle Line Numbers")
+ mi = m.add("Go to Line Number")
+ mi = m.add("Clear IRB Output")
+ mi = m.add("Copy IRB Output to Editor")
+ mi = m.add("Reload Scripts List")
+ mi = m.add("Reload demos from assets")
+ mi = m.add("About")
+ mi.set_icon R::drawable::ic_menu_info_details
+
+ true
+ end
+
+ def on_options_item_selected(mi)
+ case mi.title.to_s
+ when "Save"
+ save(@edit_name.getText.toString, @edit_script.getText.toString)
+ when "Execute"
execute @edit_script.getText.toString,
"[Running editor script (#{@edit_name.getText})]"
@tabs.setCurrentTabByTag("irb")
- end
-
- add_menu("New", R::drawable::ic_menu_add) do
+ when "New"
@edit_name.setText "untitled.rb"
@edit_script.setText ""
@tabs.setCurrentTabByTag("editor")
- end
-
- add_menu("Edit history", R::drawable::ic_menu_recent_history) do
+ when "Edit History"
@edit_name.setText "untitled.rb"
@edit_script.setText @history.join("\n")
@tabs.setCurrentTabByTag("editor")
- end
-
- add_menu("Toggle Line Numbers") do
+ when "Toggle Line Numbers"
@edit_script.toggle_show_line_numbers
- end
-
- add_menu("About", R::drawable::ic_menu_info_details) do
+ when "Go to Line Number"
+ et = edit_text(:hint => "Line number", :input_type => android.text.InputType::TYPE_CLASS_NUMBER)
+
+ goto = proc do
+ @edit_script.requestFocus
+ line = et.text.to_s.to_i - 1
+ max_line = @edit_script.getLineCount
+ line = max_line if line > max_line
+ line = 1 if line < 1
+ @edit_script.setSelection @edit_script.getLayout.getLineStart(line)
+ end
+
+ dialog = AlertDialog::Builder.new(@ruboto_java_instance).setTitle("Go to").setView(et).setPositiveButton("Go", goto).create
+ dialog.window.soft_input_mode = android.view.WindowManager::LayoutParams::SOFT_INPUT_STATE_ALWAYS_VISIBLE
+ dialog.show
+ when "Clear IRB Output"
+ @irb_text.text = ">> "
+ when "Copy IRB Output to Editor"
+ @edit_name.text = "untitled.rb"
+ @edit_script.text = @irb_text.text.to_s
+ @tabs.setCurrentTabByTag("editor")
+ when "Reload Scripts List"
+ @tabs.setCurrentTabByTag("scripts")
+ load_script_list
+ when "Reload demos from assets"
+ toast recopyDemos("demo-scripts", Dir.pwd).join("\n")
+ load_script_list
+ when "About"
AlertDialog::Builder.new(self).
setTitle("About Ruboto IRB (demo script)").
setView(scroll_view do
@@ -122,49 +322,36 @@
show
end
- add_menu("Reload scripts list") do
- @tabs.setCurrentTabByTag("scripts")
- load_script_list
- end
+ true
+ end
- add_menu("Reload demos from assets") do
- getAssets.list('demo-scripts').map(&:to_s).each do |s|
- buf = getAssets.open("demo-scripts/#{s}", AssetManager::ACCESS_BUFFER)
- contents = []
- b = buf.read
- until b == -1 do
- contents << b.chr
- b = buf.read
- end
- toast_result save(s, contents.join), "#{s} copied", "#{s} copy failed"
- end
- end
+ def on_create_context_menu(menu, view, menu_info)
+ mi = menu.add("Edit")
+ mi = menu.add("Execute")
+ mi = menu.add("Delete")
true
end
- #
- # Script list context menu items
- #
-
- handle_create_context_menu do |menu, view, menu_info|
- add_context_menu("Edit") {|pos| edit @scripts_list[pos]}
+ def on_context_item_selected(mi)
+ pos = mi.menu_info.position
- add_context_menu("Execute") do |pos|
+ case mi.title.to_s
+ when "Edit"
+ edit @scripts_list[pos]
+ when "Execute"
begin
execute IO.read(@scripts_list[pos]), "[Running #{@scripts_list[pos]}]"
rescue
toast "#{@scripts_list[pos]} not found!"
end
- end
-
- add_context_menu("Delete") do |pos|
+ when "Delete"
@confirm_delete = @scripts_list[pos]
- AlertDialog::Builder.new(self).
+ AlertDialog::Builder.new(@ruboto_java_instance).
setMessage("Delete #{@confirm_delete}?").
setCancelable(false).
- setPositiveButton("Yes", @dialog_click).
- setNegativeButton("No", @dialog_click).
+ setPositiveButton("Yes", (proc{|d,w| my_dialog_click(d,w)})).
+ setNegativeButton("No", (proc{|d,w| my_dialog_click(d,w)})).
create.
show
end
@@ -176,7 +363,7 @@
# Delete confirmation dialog buttons
#
- @dialog_click = proc do |dialog, which|
+ def my_dialog_click(dialog, which)
if @confirm_delete and which == DialogInterface::BUTTON_POSITIVE
begin
File.delete @confirm_delete
@@ -193,7 +380,8 @@
# Tab change
#
- @on_tab_change_listener = proc do |tab|
+ def tab_changed(tab)
+ @current_tab = tab
if tab == "scripts"
getSystemService(Context::INPUT_METHOD_SERVICE).
hideSoftInputFromWindow(@tabs.getWindowToken, 0)
@@ -208,68 +396,11 @@ def set_script_padding(l, t, r, b)
@edit_script.setPadding(l, t, r, b)
end
- @line_number_draw = Proc.new do
- @show_line_numbers = context.getPreferences(Context::MODE_PRIVATE).getBoolean("LineNumbers", true)
- @line_rect = android.graphics.Rect.new
- @paint = android.graphics.Paint.new
- @paint.color = (text_colors.default_color & android.graphics.Color.argb(0xAA, 0xFF, 0xFF, 0xFF))
- @paint.text_size = (text_size * 0.6)
- @current_left = @default_left = padding_left
-
- def toggle_show_line_numbers
- @show_line_numbers = !@show_line_numbers
- prefs_editor = context.getPreferences(Context::MODE_PRIVATE).edit
- prefs_editor.putBoolean("LineNumbers", @show_line_numbers)
- prefs_editor.commit
- invalidate
- end
-
- def min(a, b)
- a > b ? b : a
- end
-
- def max(a, b)
- a > b ? a : b
- end
-
- def calculate_padding
- new_padding = @default_left + ((!@show_line_numbers || line_count == 0) ? 0 :
- ((Math.log10(line_count).to_i + 1) * @paint.text_size))
-
- unless new_padding == @current_left
- @current_left = new_padding
- set_padding(new_padding, padding_top, padding_right, padding_bottom)
- end
- end
-
- def on_draw(canvas)
- if (@show_line_numbers)
- topLineNumber = max(1, ((scroll_y - extended_padding_top) / line_height))
- bottomLineNumber = min(line_count, topLineNumber + (height / line_height).to_i)
-
- canvas.save
-
- canvas.clipRect(0,
- extended_padding_top + scroll_y,
- padding_left + scroll_x,
- bottom - top - extended_padding_bottom + scroll_y)
-
- topLineNumber.upto(bottomLineNumber) do |i|
- getLineBounds(i - 1, @line_rect)
- canvas.drawText(i.to_s, @default_left + scroll_x, @line_rect.bottom - 8, @paint)
- end
-
- canvas.restore
- end
- calculate_padding
- end
- end
-
#
# Key actions for keeping the history of the IRB EditText
#
- @on_key_listener = proc do |view, key_code, event|
+ def my_key_listener(view, key_code, event)
rv = false
if [KeyEvent::ACTION_DOWN, KeyEvent::ACTION_MULTIPLE].include? event.getAction
if (@cursor > 0 and key_code == KeyEvent::KEYCODE_DPAD_UP) or
@@ -298,13 +429,15 @@ def on_draw(canvas)
# Save and restore state of history text
#
- handle_save_instance_state do |bundle|
+ def on_save_instance_state(bundle)
+ super
@history[@cursor] = @irb_edit.getText.toString if @cursor == (@history.size - 1)
bundle.putString("history", @history.join("\n"))
bundle.putInt("cursor", @cursor)
end
- handle_restore_instance_state do |bundle|
+ def on_restore_instance_state(bundle)
+ super
@history = bundle.getString("history").nil? ? [""] : bundle.getString("history").split("\n")
@history << "" if bundle.getString("history") and bundle.getString("history")[-1] == "\n"
@cursor = bundle.getInt("cursor").nil? ? 0 : bundle.getInt("cursor")
@@ -341,14 +474,40 @@ def execute source, display=nil
end
end
- def save name, source
+ def save(name, source)
begin
File.open(name, 'w') {|file| file.write(source)}
@tabs.setCurrentTabByTag("scripts")
toast "Saved #{name}"
load_script_list
+ true
rescue
toast "Save failed!"
+ false
+ end
+ end
+
+ def recopyDemos(from, to)
+ FileUtils.makedirs to
+ rv = []
+ getAssets.list(from).map(&:to_s).each do |s|
+ if getAssets().list("#{from}/#{s}").length == 0
+ buf = getAssets.open("#{from}/#{s}", android.content.res.AssetManager::ACCESS_BUFFER)
+ contents = []
+ b = buf.read
+ until b == -1 do
+ contents << b.chr
+ b = buf.read
+ end
+ begin
+ File.open("#{to}/#{s}", 'w') {|file| file.write(contents.join)}
+ rv << "#{s} copied"
+ rescue
+ rv << "#{s} copy failed"
+ end
+ else
+ rv = rv + recopyDemos("#{from}/#{s}", "#{to}/#{s}")
+ end
end
end
@@ -381,4 +540,3 @@ def about_text
CC ShareAlike 2.5"
end
end
-

0 comments on commit 401afa0

Please sign in to comment.
Something went wrong with that request. Please try again.