Giter Site home page Giter Site logo

Comments (16)

ccoupe avatar ccoupe commented on September 2, 2024

As currently written, there is no way in Shoes to reliably manage other Apps/Wiindows. It is confounded by the other (mostly unwritten about) url/visit style which does allow modal dialog like control . My sample ytm.rb at http://walkabout.mvmanila.com/public/share/ytm.rb shows this style of Shoes programming (you'll need http://walkabout.mvmanila.com/public/share/ytmsec.csv
ytmsec.csv to run the code, you might need the icon too).

An IRB facility does need that kind of modal control and inspection into Shoes.apps (kind of like gdb has to control its apps and threads and set values in the target. Perhaps your irb could be written in that style and if you need some api's into Shoes internals we can write them. Just a suggestion.

from shoes3.

IanTrudel avatar IanTrudel commented on September 2, 2024

The code seems to be accommodating on the surface but clearly not working to manage multiple Shoes apps. One oddities in https://github.com/Shoes3/shoes3/blob/master/shoes/app.c#L80 is the usage of rb_ary_dup in shoes_apps_get, which seems like a very bad idea. Also, shoes_app_new indeed pushes the app into the array.

It might be necessary to gdb this one because even though the object is listed, some of its methods are not available. It is possible to add slots and elements to a window but not read it without previously defining local variables (such as in my IRB turtorial). I did test without rb_ary_dup on Loose Shoes but without success. Accessing contents of Shoes.APPS[0] from a second window still generates an undefined method:

Error in <unknown> line 0 | 2015-01-28 11:18:41 -0500
undefined method `contents' for (Shoes::Types::App "Shoes")
contents_simple.rb:12:in `method_missing'
contents_simple.rb:12:in `block in <main>'
eval:1:in `instance_eval'
eval:1:in `block in <main>'
-e:1:in `call'

You very well understand what I ought to do with IRB. Adding a special API will certainly work but it doesn't fix the core problem. Proper support within Shoes would most certainly make IRB an amazingly useful tool but also it would allow multiple windows applications to exist, such as what once was Gimp.

from shoes3.

IanTrudel avatar IanTrudel commented on September 2, 2024

Investigation reveals that Shoes should properly support multiple apps. The reason the contents is not available outside its scope is that Shoes::Types::App is not related to Shoes::Types::Canvas in any way.

It is however unclear why the following code snippet will display the contents. Canvas may be mixin in some way. Using Shoes IRB will not display the contents (directly, using put or info). Also, info top within a Shoes.app crashes Shoes on Windows — top would be a Canvas method.

Shoes.app {
  para "Check Shoes console (alt-/)"
  info self.class
  info contents
  info (self.class.instance_methods - Object.class.instance_methods).sort
}

REFERENCES
https://github.com/Shoes3/shoes3/blob/master/shoes/ruby.c#L4419 (Shoes::Types::App)
https://github.com/Shoes3/shoes3/blob/master/shoes/ruby.c#L4370 (Shoes::Types::Canvas)

from shoes3.

ccoupe avatar ccoupe commented on September 2, 2024

The clues are in ruby.c lines:4364 through 4394.

from shoes3.

IanTrudel avatar IanTrudel commented on September 2, 2024

The clues are in ruby.c lines:4364 through 4394.

Funny enough, on line 4392 there is cShoes = rb_define_class("Shoes", cCanvas);. Shoes is a Canvas and Shoes::Types::App is not. How would you fix this?

I did try earlier to set the parent class of cApp to cCanvas but Shoes crashed (segfault, shoes.rb:152) before displaying the splash screen. The two following wouldn't work.

  cApp = rb_define_class_under(cTypes, "App", cCanvas);
  cApp = rb_define_class("App", cCanvas);
  rb_include_module(cApp, cTypes);
  rb_define_alloc_func(cApp, shoes_app_alloc);

from shoes3.

ccoupe avatar ccoupe commented on September 2, 2024

For a maintenance release, I wouldn't fix it ;^) This code and the manipulation of self is what makes Shoes unique (and confusing). As you've discovered, modifying stuff here almost always results in unintended behavior.

from shoes3.

IanTrudel avatar IanTrudel commented on September 2, 2024

Come on, we have already triumphed over a few "couldn't, wouldn't fix". :)

from shoes3.

ccoupe avatar ccoupe commented on September 2, 2024

compares the lists produced by

Shoes.app {
  info Shoes::included_modules
  info Shoes::instance_methods
  info Shoes::Types::included_modules
  info Shoes::Types::instance_methods
  info Shoes::Types::App::instance_methods
  info self.class
}

from shoes3.

IanTrudel avatar IanTrudel commented on September 2, 2024

Updated your code for clarity in the output:

Shoes.app {
  info Shoes::included_modules
  info (Shoes::instance_methods - Object.instance_methods).sort
  info Shoes::Types::included_modules
  info (Shoes::Types::instance_methods - Object.instance_methods).sort
  info (Shoes::Types::App::instance_methods - Object.instance_methods).sort
  info self.class
}

from shoes3.

ccoupe avatar ccoupe commented on September 2, 2024

I can guess _why rb_ary_dup was used. If Window-1 gets a list of APPS[] there is no current way that Windows-1 knows that Windows-2 spawned a half dozen windows and closed 3 of them. Or that Windows-3 (IRB for example) is poking inside Windows-1 and closed a fourth windows from there.

APPS is only an [array] of Apps/Windows/Alerts it knows about at the time it is queried. For introspection we really need a dynamic tree structure of windows at that level in the tree and ways to move up, down, left and right in the tree node. Not so simple for anyone and very not backwards compatible but that's OK, IMO.

We have a data structure problem with APPS[] and we will need some hashes or nested arrays or both. For example APPS[] could return the( flat) array of all the windows it knows about at the time. as it does now for backwards compatibility. Shoes.AppTree (.e.g) could return a dynamic list of list or list of hashes or ....

Window titles cannot be use as a hash key since a scrip(s)t can change those. A global C var may already exist for counting windows that can be use to create keys or we can create one. I'm only exploring the idea. Might be a hell of lot of 'C' code to modify and app issues will bite you in the ass.

Thoughts?

from shoes3.

ccoupe avatar ccoupe commented on September 2, 2024

Before I start modifying anything, it's good to explore how this corner of Shoes works and since I'm not particularly knowledgeable with meta programming and the Shoes core class arrangement I wrote a program to explore it. https://gist.github.com/ccoupe/95e095cbb749ba7c5006 It's Shoes so all the windows stack on top so you have to spread them out manually. Ugly.

It demonstrates that one can manipulate other Shoes windows from Shoes. Not easily because you have to instance_eval to get the binding correct and string escaping can be horrendous. However for this bug report, you can do it.

To use eval(string, TOPLEVEL_BiNDING) as IRB (and others) like to do is a problem unless Shoes/irb can switch (+save/restore) the binding. It could do that I think but it would be ugly, hackish, and prone to breakage. But I'm not very clever so perhaps someone else can do better.

from shoes3.

ccoupe avatar ccoupe commented on September 2, 2024

Turns out there is an existing App.slot method documented (by @passenger94 ?) " as
no idea what this does". app.slot.contents does appear to return canvas.contents. It's at app.c:161

I would prefer the name to be 'slots' but for compatibility reasons I will dup the tiny bit of code and rename it to slots and document slots.

And I may have found a good test case for when Shoes doesn't alway default to flow layout - a bug that has bothered me forever.

@backorder' original test script has been modified to add a start block because not everything is realized at the instantly and use slot.contents.

@app = Shoes.app {
   s = stack { para "stack paragraph" }
   para "paragraph"
   info "contents: #{contents}"
   info "Shoes.APPS[0].contents: #{Shoes.APPS[0].slot.contents}"
   info "stack contents #{s.contents}"
   Shoes.app {
      info "Shoes.app(2)>>Shoes.APPS: #{Shoes.APPS}"
      begin
         info "Shoes.app(2)>>Shoes.APPS[0].contents: #{Shoes.APPS[0].slot.contents}"
      rescue Exception => e
         msg = e.backtrace.join("\n")
         error "Shoes.app(2)>>Shoes.APPS[0]:\n#{e.message}\n#{msg}"
      end
   }
}

Shoes.app {
   flow { para "flow paragraph" }
   info "Shoes.app(3)>>Shoes.APPS[1].contents: #{Shoes.APPS[1].slot.contents}"
   start do
     begin
      info "Shoes.app(3)>>Shoes.APPS: #{Shoes.APPS.inspect}"
     rescue Exception => e
      msg = e.backtrace.join("\n")
      error "Shoes.app(2)>>Shoes.APPS:\n#{e.message}\n#{msg}"
     end
     begin
      info "Shoes.app(3)>>Shoes.APPS[0].contents: #{Shoes.APPS[0].slot.contents}"
     rescue Exception => e
      msg = e.backtrace.join("\n")
      error "Shoes.app(2)>>Shoes.APPS[0]:\n#{e.message}\n#{msg}"
     end
   end
}

Shoes.show_log

Also you guys should join the new mailing list even if you just want to lurk.

from shoes3.

IanTrudel avatar IanTrudel commented on September 2, 2024

Seems like it is working as it should. It does feel a bit overkill to have to used a slot method rather than just APPS. Changing APPS to reflect slot behaviour might need much work. This technique using slot on APPS should be documented in the manual if no other steps are taken on this issue here. Excellent work, @ccoupe!

from shoes3.

ccoupe avatar ccoupe commented on September 2, 2024

It's definitely requires a long wiki article about how to poke around inside the DSL. The start() method was also critical in the above example because that's how things work. The manual has been updated for 3.2.25

from shoes3.

ccoupe avatar ccoupe commented on September 2, 2024

Folks might be interested in the wiki article: https://github.com/Shoes3/shoes3/wiki/Poking-in-Shoes.app which adds a button in another window using the methods discovered above.

from shoes3.

IanTrudel avatar IanTrudel commented on September 2, 2024

This is a very good wiki article. Shoes is getting gradually demystified.

from shoes3.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.