I was wondering if it was possible to change the my Shoes app's icon? I imagine its style-oriented, but I haven't been able to find anything on it.
Is this possible?
You can do it in Green Shoes, but you have to go under the hood a bit. Here's some very simple code I wrote for SciRuby:
class Shoes
class App
def icon filename=nil
filename.nil? ? win.icon : win.icon = filename
end
class << self
def default_icon= filename
Gtk::Window.set_default_icon(filename)
end
end
end
end
The second method is optional; you can use it to set the icon for your whole app, I think. The first method sets the icon for the current window, and you would use it like so:
DIR = Pathname.new(__FILE__).realpath.dirname.to_s
ICON_PATH = File.join(DIR, '..', 'static', 'my-icon.png')
# ...
Shoes.app :title => "My App" do
icon ICON_PATH
end
And for the default:
Shoes::App.default_icon = ICON_PATH
I use a 128x128 png file. I tried a 500x500 one and it didn't work properly. In the code above, ICON_PATH, from the root of your project directory, should be ./static/my-icon.png.
You may also need to require "gtk2" somewhere for the default_icon= method.
I don't believe this is possible from within Shoes. This is based on extensive searching, both online and in the source code.
However, there are a couple things external to Shoes that work. One is to simply change the file #{DIR}/static/shoes-icon.png, which is where the runtime pulls its icon from. The other is to change the hardcoded value in the file libshoes.so (or your OS's equivalent); you could use a hex editor, or any other editor that wouldn't mess the file up. Note that for the hardcoded editing to work without crashing, you have to replace the hardcoded string with something of the same length.
Use IcoFx. _why himself suggested this utility on the mailing list. You will find the instruction in the tutorial section of the icoFX website.
So far, I am not sure that this is actually possible. in OS X, I was able to modify the package contents to change what the plist is pointing to in terms of icons. However, when the application runs, it uses the Shoes' runtime icon.
I have no clue how you'd do this on Windows.
Related
I am trying to build a GUI with ruby Shoes to select a background image for my desktop. As I am struggling with a particular part of my idea I am going to describe just the problem part, the rest works fine.
Here's the code of my ruby Shoes app:
Shoes.app :title => "Images!" do
stack do
#img1 = image "desktop_pic", :width => 200, :height => 100
button "Change image", :margin => 25 do
#img1.path = "/home/njutik/preview_desktop_pic"
end
end
end
Here's what the result looks like when I start my Shoes app:
result_at_beginning
In the background there is a different ruby script running which generates a new background-image and stores it as preview_desktop_pic.
So when I click the Change image-button, the path of #img1 gets adjusted and I see the new image:
result_after_clicking_change_button
That's fine so far. My problem is, that nothing happens when I click the Change image-button again. Of course in the meantime there is already a new image preview_desktop_pic so the code line
#img1.path = "/home/njutik/preview_destkop_pic"
which is executed each time I press the Change image-button should show me a new picture but nothing happens. Even when I delete the preview_desktop_pic from the folder and then press the Change image-button there is still no change at all and all I see is the same picture shown after clicking the Change image-button for the first time.
So my question is: what am I doing wrong and how can I make the Shoes app show the current preview_desktop_pic every time I press the Change image-button?
Any hints would be really great!
Update: After the comment of 7stud I tried to define a singleton method for the button. Like this:
#change_image = button "Change image"
def #change_image.click
#img1.path = "/home/njutik/preview_login_background"
end
#change_image.click
But that did not help - nothing changed.
Then I tried this:
def #img1.reload
#img1.path = "/home/njutik/preview_login_background"
end
button "Change image" do
#img1.reload
end
But this also did not help. I thought that by defining singleton methods I would delete the cache memory.
Any further hints would be really helpful.
I don't think you are doing anything wrong. I think that what you are seeing has to do with image caching, which Shoes uses for efficiency. If ten windows all use the same image, Shoes does not fetch the file from disk (or download the file from the web) for each window. Instead, Shoes caches the image used in the first window, and when the other windows use the same path for the Image, Shoes retrieves the image from the cache. As a result, if the path for your Image doesn't change, it looks like Shoes uses the cached image. It would be nice if an Image in Shoes had a reload() method, which would force Shoes to ignore the cache and go get the image again.
In your app, the first button click works because the Image's path changes from "/desktop_pic" to "/home/njutik/preview_desktop_pic". Subsequent clicks do not change the Image's path.
To change the image, the new image must have a different name than the previous one. I do not know why but it works for me then.
I have recently been learning how to program with the Clutter GUI toolkit. One thing I haven't been able to figure out is how to set the programs title and icon for the window manager.
As illustrated in the image below, Gnome Shell says that the program name is "Unknown" and that the program does not have an icon.
So, how do I do this?
you cannot do this from Clutter: the windowing system API inside Clutter only allows basic operations.
if you want proper integration in a windowing system you should use Clutter-GTK, and embed a ClutterStage into a Gtk application.
In theory, you can do that in this way:
let stage = Clutter.Stage.get_default ();
let gdkWind = ClutterGdk.get_stage_window (stage);
// The list most containt icons in different sizes.
let list = [GdkPixbuf.Pixbuf.new_from_file("test.png")];
gdkWind.set_icon_list(list);
//The next line not work
gdkWind.set_title("This title is not added");
In practice, you only will can load the icon and the windows title, but not the task bar title for the windows. The set_title won't work as Gdk.Window reference say it will (https://people.gnome.org/~gcampagna/docs/Gdk-3.0/Gdk.Window.set_title.html). Is then a Clutter issue, because is not a GDK "special case". But well is not working.
How do I change the application title in the Mac menu bar programmatically (after starting the application)?
I know that I can set it before running the program via CFBundleName in the Info.plist file. However, I need to change it after initializing the application. Manipulating my own Info.plist also won't work.
There is no official API to do so, but in this discussion someone hinted that there is a secret function call that changes the bundle name / menubar title:
"There is SPI you can use if you look hard enough around for it, but
I'm not going to point anybody to it unless they can justify why they
need to use it :-)"
I think Java uses something similar, too. So what's the secret API?
OK, I've found a way. This is the code in Python (taken from here). It could use some cleaning and some error handling, but it works. The key is the undocumented CPSSetProcessName from ApplicationServices.
def _osx_set_process_name(app_title):
""" Change OSX application title """
from ctypes import cdll, c_int, pointer, Structure
from ctypes.util import find_library
app_services = cdll.LoadLibrary(find_library("ApplicationServices"))
if app_services.CGMainDisplayID() == 0:
print "cannot run without OS X window manager"
else:
class ProcessSerialNumber(Structure):
_fields_ = [("highLongOfPSN", c_int),
("lowLongOfPSN", c_int)]
psn = ProcessSerialNumber()
psn_p = pointer(psn)
if ( (app_services.GetCurrentProcess(psn_p) < 0) or
(app_services.SetFrontProcess(psn_p) < 0) ):
print "cannot run without OS X gui process"
print "setting process name"
app_services.CPSSetProcessName(psn_p, app_title)
return False
If you call it right away, it changes the process name in the Activity Monitor. I had to call it after a small timeout for some reason to also change the Menubar name:
import gobject
gobject.timeout_add(100, _osx_set_process_name, "MyTitle")
Note that if you combine this with an .app package you can get a really nice system integration of a python app. While you can change the Icon, the Finder display name, ..., all methods I tried leave the CFBundleName (the one in the Menu bar) to "Python". (This answer for example only changes the long name (displayed over dock icons). There are plenty others that almost work.)
While this answer gives the intended result, it's not very elegant. I'd appreciate some insight into why I need the timeout... I think Python or pygtk changes the process name itself when I first import gtk or run the main loop.
I want to write a small text-editor in Ruby for learning the basics. I want to show all the possible text-manipulation options in one single menu. Once the option is selected, the string typed in an Input box will be altered accordingly.
I am not following how to prepare this basic GUI.
You can have a look at FXRuby. Here is a small tutorial to make a text editor using FXRuby.http://rubylearning.com/satishtalim/fxruby.html
On Windows, your best bet is using JRuby and SWT. If you plan to switch to Mac OS X, you can think about MacRuby.
You can use visualruby, and you could write it in about an hour:
http://visualruby.net
You would build your window in the glade interface designer, then add a menu to your window with all your menu options. All of this can be done in the glade software so no code is required. Then you could give your menu options names that you reference later:
menuClear
menuIndent
menuComment
menuQuit
etc.
You could have the editor itself be a textview named textview1.
Then your code could be:
class MyEditor
def show
load_glade(__FILE__)
show_window()
end
def menuClear__clicked
#builder["textview1"].buffer.text = ""
end
def menuIndent__clicked
current_line = tab + current_line
end
def menuComment__clicked
current_line = "#" + current_line
end
def menuQuit__clicked
destroy_window
end
end
MyEditor.new.show
I think its easier than any of the other toolkits, and its more robust because its GTK.
All of the above statement are explained on the website. Good luck.
Ruby got Tk builtin, or you can use ffi-tk, which is a bit closer to tcl/tk. ver is an example. tkdocs is quite comprehensive, and it's got a nice API imo. And the Text Widget is really powerful.
If you have previous Java/Swing experience you might want to look at JRuby and Monekybars.
I was taking a look at Shoes which seems like a very nice tool for quick GUI applications. The common elements/controls, however, don't seem to include the equivalent of a list/report view (e.g., ListView in Windows, NSTableView in OS X).
Did I just miss this, or does it not (yet) exist?
If you mean output a large quantity of textual data such as a report or table then there's a nice simple app in the shoebox called the Simple Table Class which works very nicely. Before I found it i was ready to give shoes up - but this class solved my problem in minutes.
Looking for it i stumbled across laces which includes a class called The Tablie. I haven't tried it but I am suddenly intrigued....
There doesn't seem to be. Shoes Classes doesn't seem to mention anything similar.
I guess it shouldn't be too difficult to manually create something similar. The good-vjot.rb sample script is probably the closest I can think of, although it's hardly identical..
Martin DeMello's Gooey Challenge
(Using Shoes widgets to build custom Shoes controls) may be of some help
Shoes.app do
stack do
#l = list_box :items => ["YES", "NO"] do
alert #l.text
end
end
end