Skip to content

Commit

Permalink
Fix most self bugs - use Scarpe::App as self nearly always.
Browse files Browse the repository at this point in the history
Make display properties properly inheritable
Move DocumentRoot special behavior into app, make it 'just a Flow'
Remove unused app-option override code in ControlInterface
  • Loading branch information
noahgibbs committed Jul 4, 2023
1 parent 8e931fe commit 329f52c
Show file tree
Hide file tree
Showing 18 changed files with 206 additions and 152 deletions.
18 changes: 18 additions & 0 deletions examples/selfitude.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
def printish(msg)
#$stderr.puts msg
File.open("/tmp/shoesy_stuff.txt", "a") do |f|
f.write(msg + "\n")
end
end

Shoes.app do
printish "Self top: #{self.inspect}" # It's an instance of Shoes::App, yes
stack do
printish "Self in stack: #{self.inspect}" # Yup, here too
end
button("Clickity") do
alert("You clicked me!")
printish "Self in button handler: #{self.inspect}" # And here too
end
end

45 changes: 42 additions & 3 deletions lib/scarpe/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,24 @@ def initialize(
debug: ENV["SCARPE_DEBUG"] ? true : false,
&app_code_body
)
log_init("Scarpe::App")

if Scarpe::App.instance
@log.error("Trying to create a second Scarpe::App in the same process! Fail!")
raise "Cannot create multiple Scarpe::App objects!"
else
Scarpe::App.instance = self
end

log_init("Scarpe::App")

@do_shutdown = false

super

# This creates the DocumentRoot, including its corresponding display widget
@document_root = Scarpe::DocumentRoot.new

@slots = []

# Now create the App display widget
create_display_widget

Expand Down Expand Up @@ -68,7 +70,31 @@ def init
send_shoes_event(event_name: "init")
return if @do_shutdown

@document_root.instance_eval(&@app_code_body)
::Scarpe::App.instance.with_slot(@document_root, &@app_code_body)
end

# "Container" widgets like flows, stacks, masks and the document root
# are considered "slots" in Scarpe parlance. When a new slot is created,
# we push it here in order to track what widgets are found in that slot.
def push_slot(slot)
@slots.push(slot)
end

def pop_slot
@slots.pop
end

def current_slot
@slots[-1]
end

def with_slot(slot_item, &block)
return unless block_given?

push_slot(slot_item)
Scarpe::App.instance.instance_eval(&block)
ensure
pop_slot
end

# This isn't supposed to return. The display service should take control
Expand All @@ -87,3 +113,16 @@ def destroy(send_event: true)
end
end
end

# DSL methods
class Scarpe::App
def background(...)
current_slot.background(...)
end

def border(...)
current_slot.border(...)
end

alias_method :info, :puts
end
8 changes: 2 additions & 6 deletions lib/scarpe/document_root.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
# frozen_string_literal: true

class Scarpe
class DocumentRoot < Scarpe::Widget
include Scarpe::Background

class DocumentRoot < Scarpe::Slot
def initialize
super

create_display_widget
end

# This can be absolutely huge in console output, and it's frequently printed.
# The default inspect string can be absolutely huge in console output, and it's frequently printed.
def inspect
"<Scarpe::DocumentRoot>"
end

alias_method :info, :puts

def all_widgets
out = []

Expand Down
47 changes: 47 additions & 0 deletions lib/scarpe/download.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

require "net/http"
require "openssl"
require "nokogiri"

class Scarpe::Widget
def download(url)
Thread.new do
begin
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Get.new(uri.request_uri)

http.request(request) do |response|
case response
when Net::HTTPSuccess
# content = response.body

# headers = response.header

html_get_title(content)
else
Scarpe.error("Failed to download content. Response code: #{response.code}")
end
end
rescue StandardError => e
Scarpe.error("Error occurred while downloading: #{e.message}")
end
end
end

private

def html_get_title(content)
doc = Nokogiri::HTML(content)

title = doc.at_css("title")&.text&.strip || ""

# headings = doc.css("h1").map(&:text)

title
end
end
7 changes: 2 additions & 5 deletions lib/scarpe/flow.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# frozen_string_literal: true

class Scarpe
class Flow < Scarpe::Widget
include Scarpe::Background
include Scarpe::Border

class Flow < Scarpe::Slot
display_properties :width, :height, :margin, :padding

def initialize(width: nil, height: "100%", margin: nil, padding: nil, &block)
Expand All @@ -13,7 +10,7 @@ def initialize(width: nil, height: "100%", margin: nil, padding: nil, &block)
# Create the display-side widget *before* instance_eval, which will add child widgets with their display widgets
create_display_widget

instance_eval(&block)
Scarpe::App.instance.with_slot(self, &block) if block_given?
end
end
end
1 change: 1 addition & 0 deletions lib/scarpe/shape.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def initialize(left: nil, top: nil, path_commands: nil, &block)

super()
create_display_widget

instance_eval(&block) if block_given?
end
end
Expand Down
6 changes: 6 additions & 0 deletions lib/scarpe/slot.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class Scarpe::Slot < Scarpe::Widget
include Scarpe::Background
include Scarpe::Border
end
54 changes: 3 additions & 51 deletions lib/scarpe/stack.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
# frozen_string_literal: true

require "net/http"
require "openssl"
require "nokogiri"

class Scarpe
class Stack < Scarpe::Widget
include Scarpe::Background
include Scarpe::Border
class Stack < Scarpe::Slot
include Scarpe::Spacing

display_properties :width, :height, :margin, :padding, :scroll, :margin_top, :margin_left, :margin_right, :margin_bottom, :options
Expand All @@ -21,50 +15,8 @@ def initialize(width: nil, height: "100%", margin: nil, padding: nil, scroll: fa
super

create_display_widget
# Create the display-side widget *before* instance_eval, which will add child widgets with their display widgets
instance_eval(&block) if block_given?
end
end

class Widget
def download(url)
Thread.new do
begin
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Get.new(uri.request_uri)

http.request(request) do |response|
case response
when Net::HTTPSuccess
# content = response.body

# headers = response.header

get_title(content)
else
Scarpe.error("Failed to download content. Response code: #{response.code}")
end
end
rescue StandardError => e
Scarpe.error("Error occurred while downloading: #{e.message}")
end
end
end

private

def get_title(content)
doc = Nokogiri::HTML(content)

title = doc.at_css("title")&.text&.strip || ""

# headings = doc.css("h1").map(&:text)

title
# Create the display-side widget *before* running the block, which will add child widgets with their display widgets
Scarpe::App.instance.with_slot(self, &block) if block_given?
end
end
end
30 changes: 16 additions & 14 deletions lib/scarpe/widget.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,11 @@ class Widget < DisplayService::Linkable
include Scarpe::Colors

class << self
attr_accessor :widget_classes, :alias_name

def alias_as(name)
self.alias_name = name
end
attr_accessor :widget_classes

def inherited(subclass)
self.widget_classes ||= []
self.widget_classes << subclass
Scarpe::Widget.widget_classes ||= []
Scarpe::Widget.widget_classes << subclass
super
end

Expand All @@ -30,7 +26,7 @@ def dsl_name
end

def widget_class_by_name(name)
widget_classes.detect { |k| k.dsl_name == name.to_s || k.alias_name.to_s == name.to_s }
widget_classes.detect { |k| k.dsl_name == name.to_s }
end

private
Expand All @@ -56,16 +52,20 @@ def display_property(name)
linkable_properties_hash[name] = true
end

# Add these names as display properties
def display_properties(*names)
names.each { |n| display_property(n) }
end

def display_property_names
linkable_properties.map { |prop| prop[:name] }
parent_prop_names = self != Scarpe::Widget ? self.superclass.display_property_names : []

parent_prop_names | linkable_properties.map { |prop| prop[:name] }
end

def display_property_name?(name)
linkable_properties_hash[name.to_s]
linkable_properties_hash[name.to_s] ||
(self != Scarpe::Widget && superclass.display_property_name?(name))
end
end

Expand All @@ -91,9 +91,11 @@ def bind_no_target_event(event_name, &block)
bind_shoes_event(event_name:, &block)
end

def display_properties
def display_property_values
all_property_names = self.class.display_property_names

properties = {}
self.class.display_property_names.each do |prop|
all_property_names.each do |prop|
properties[prop] = instance_variable_get("@" + prop)
end
properties["shoes_linkable_id"] = self.linkable_id
Expand All @@ -104,7 +106,7 @@ def create_display_widget
klass_name = self.class.name.delete_prefix("Scarpe::").delete_prefix("Shoes::")

# Should we save a reference to widget for later reference?
DisplayService.display_service.create_display_widget_for(klass_name, self.linkable_id, display_properties)
DisplayService.display_service.create_display_widget_for(klass_name, self.linkable_id, display_property_values)
end

attr_reader :parent
Expand Down Expand Up @@ -177,7 +179,7 @@ def method_missing(name, *args, **kwargs, &block)
widget_instance = klass.new(*args, **kwargs, &block)

unless klass.ancestors.include?(Scarpe::TextWidget)
widget_instance.set_parent(self)
widget_instance.set_parent Scarpe::App.instance.current_slot
end

widget_instance
Expand Down
2 changes: 2 additions & 0 deletions lib/scarpe/widgets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@

require_relative "fill"

require_relative "slot"
require_relative "document_root"
require_relative "para"
require_relative "stack"
require_relative "flow"
require_relative "download"
require_relative "button"
require_relative "image"
require_relative "edit_box"
Expand Down
2 changes: 1 addition & 1 deletion lib/scarpe/wv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
require_relative "wv/arc"

require_relative "wv/app"
require_relative "wv/document_root"
require_relative "wv/para"
require_relative "wv/stack"
require_relative "wv/flow"
require_relative "wv/document_root"
require_relative "wv/button"
require_relative "wv/image"
require_relative "wv/edit_box"
Expand Down
Loading

0 comments on commit 329f52c

Please sign in to comment.