Refresh an image in Rebol - user-interface

I've been working on this for a while. Gone through the REBOL docs and the answers here, but I am stumped. Can someone please tell me how to get an REBOL GUI image to update to another image? Here's the code I've gotten after two days of hacking at it. Any help would he appreciated.
REBOL [
Title: "Yvonne View"
]
yvonne: func[] [
parts: probe parse read http://pics.mytrapster.com/yvonne.php {="}
load to-string parts/6
]
img1: to-image (load-image yvonne)
img2: to-image (load-image yvonne)
v1: layout [
size 500x500
b: image img1
btn "Refresh" [ b: img2 ]
btn "Quit" [quit]
]
view v1
The url loads. The quit button works. The "b" variable just doesn't clear and update.
Thanks.

The way you can update an image is by using set-face
Change the refresh button line to:
btn "Refresh" [set-face b img2]
Alternatively if you are manually changing a pane of a face, you can use show (i.e. show b)

Related

Leaflet imageOverlay click event

I need an on click event on image overlays.
According to the documentation Leaflet documentation imageOverlay (as far as I understand it correctly)
I can use the interactivity option to receive mouse events.
If true, the image overlay will emit mouse events when clicked or hovered.
I thought it would work something like that:
let newOverlay = L.imageOverlay(imageUrl, imageBounds, {opacity:0.5, interactive: true});
newOverlay.on('click', function(d) {alert('I have been clicked ' # this)});
My final goal is to get the pixel coordinates of the click event, relative to the image on which the click event happened.
Can someone spot my error or is there another approach?
I tried for hours, but I did not succeed :(
I am thankful for every help.
Kind regards
Niklas
Just a little mistake
Change # to + so you will get alert message: I have been clicked [object Object]
alert('I have been clicked ' # this)
to
alert('I have been clicked ' + this)
let newOverlay = L.imageOverlay(imageUrl, imageBounds, {opacity:0.5, interactive: true});
newOverlay.on('click', function(d) {alert('I have been clicked ' + this)});

Creating gui objects in Red language

Is it possible to use make command to create gui object in Red/Rebol. I tried following:
view [
do [guiobj: make object! [
t: text "text"
f: field "fld"
b: button "button" ] ; end make object
obj1: make guiobj
obj2: make guiobj ] ; end do
below
obj1
obj2 ] ; end view
But I get following error:
*** Script Error: field has no value
*** Where: f
*** Stack: view layout do-safe
*** Script Error: VID - invalid syntax at: [obj1 obj2]
*** Where: do
*** Stack: view layout cause-error
I know compose can be used but can above code be made to work using make and object commands?
According to the documentation: Face objects are clones of face! template object.
It's possible to build up UIs without using VID—understanding that will help you understand how to manipulate the output from layout (and view). What you lose building things from scratch is the layout feature that VID offers, but we can get the best from both worlds. Let's have a go:
Window Without VID
First we'll need a place to put all our elements:
our-window: make face! [
type: 'window
text: "Our Window"
size: 500x500
]
Now let's stick some things in there:
our-window/pane: reduce [
make face! [
type: 'text
offset: 20x20
size: 160x28
text: "Text"
]
make face! [
type: 'field
offset: 200x20
size: 160x24
text: "Field"
]
make face! [
type: 'button
offset: 380x20
size: 160x28
text: "Button"
]
]
And now we can take a look at it:
view our-window
Note that the objects in our-window/pane are kind-of like the objects that would be generated in this example:
our-vid-window: layout [
text 160 "Text"
field 160 "Field"
button 160 "Button"
]
As I said, with this approach you have to manage sizes and offsets yourself. What we can do is generate our row, take those face objects and append it to our window.
Stealing Generated Faces from VID
Indeed we can actually create these objects with layout and drop them in our-window:
make-row: func [/local row face kid][
row: layout copy/deep [ ; copy so the strings are unique
text 160 "Text"
field 160 "Field"
button 160 "Button"
]
...
]
Using techniques from this answer you can even apply global words to each of these faces and will still work.
Before we do though, we're going to check if our-window has any children and adjust the offset of each of the new faces to appear below the last child:
if kid: last our-window/pane [
...
foreach face row/pane [
face/offset/y: face/offset/y + kid/offset/y + kid/size/y
]
]
To get the window sizing right, we're also going to adjust the generated row size and apply thus:
row/size/y: row/size/y + kid/offset/y + kid/size/y
...
our-window/size: row/size
And then the fun part:
append our-window/pane row/pane
Bringing this all together, we can generate a nicely sized window.
our-window: layout [
button "Add a Row" [make-row]
]
make-row: func [/local row face kid][
row: layout copy/deep [
text 160 "Text"
field 160 "Field"
button 160 "Button"
]
if kid: last our-window/pane [
row/size/y: row/size/y + kid/offset/y + kid/size/y
foreach face row/pane [
face/offset/y: face/offset/y + kid/offset/y + kid/size/y
]
]
our-window/size: row/size
append our-window/pane row/pane
]
make-row
make-row
make-row
view our-window

Making GUI objects in Red language

I have following simple code for a small panel:
view [
t: text "label"
f: field
button "Click here" [t/text: f/text] ]
But I have to make 2 of them and put them on one window. I want to create single object class and make 2 objects out of it. I see that objects can be created as follows:
obj: object [
view [
t: text "label"
f: field
button "Click here" [t/text: f/text] ] ]
view [
obj
obj ]
But I get following error:
*** Script Error: VID - invalid syntax at: [obj obj]
*** Where: do
*** Stack: view layout cause-error
How can this be done? Thanks for your help.
Edit: I tried with do but could manage only with does:
myview: object [
show: does [view[
below
t: text "1st time"
f: field "Enter value"
button "Click here" [f/text "clicked"]
area] ] ]
myview/show
print "READY TO SHOW 2nd OBJECT: "
myview2: copy myview
myview2/show
I want to create single object class and make 2 objects out of it.
There is no object class system in Red, so you should really try first to grasp the basic Red concepts before trying more complex GUI constructs. Red is a very flexible data-oriented language, so you can use that to your advantage by, for example, building parametrized block templates, and assembling them to form a correct block of VID code. Here is an example:
make-row: func [label [string!] but-label [string!]][
compose [
t: text (label)
f: field
b: button (but-label) [face/extra/1/text: face/extra/2/text]
do [b/extra: reduce [t f]]
]
]
view compose [
(make-row "label" "Click") return
(make-row "label2" "Click2")
]
Understanding the face tree (analog to the HTML DOM, just way simpler), is an important part of mastering Red's GUI system. As there is no much documentation yet (you can start with http://docs.red-lang.org), you are welcome to ask live questions on red/help Gitter room.
To work with objects instead of in the VID dialect, replace view with layout:
lay: layout [
t: text "label"
f: field
button "Click here" [t/text: f/text]
]
view lay
You can then inspect it like any other object: ?? lay.
For example, to access the contents of lay with pane:
>> ? lay/pane/1
However, a more useful function may be dump-face:
>> dump-face lay
Type: window Style: none Offset: 833x548 Size: 270x45 Text: "Red: untitled"
Type: text Style: text Offset: 10x10 Size: 80x24 Text: "label"
Type: field Style: field Offset: 100x10 Size: 80x24 Text: none
Type: button Style: button Offset: 190x9 Size: 70x25 Text: "Click here"
== make object! [
type: 'window
offset: 833x548
...
panels are useful to group objects together:
>> dump-face blay: layout [p: panel button "hi"]
Type: window Style: none Offset: none Size: 292x220 Text: none
Type: panel Style: panel Offset: 10x10 Size: 200x200 Text: none
Type: button Style: button Offset: 220x9 Size: 62x25 Text: "hi"
== make object! [
type: 'window
offset: none
...
But it's probably easier to use the VID dialect with compose to build up stuff first.
See also this question
I guess what you are looking for are styles and not objects in order to create a layout. Until now there is no official stylize function in Red. But you can create your layout dynamically like this
view repeat i 2 [
tname: to-word rejoin ['t i]
fname: to-word rejoin ['f i]
append v: [] compose/deep [
(to-set-word tname) text "label"
(to-set-word fname) field
button "click here" [
(to-set-path compose [(tname) text])
(to-path compose [(fname) text])
]
]
]
You can just append a predefined block of words many times to the block you want to view and you will get repeated elements.
txt_btn: [
t: text "label"
f: field
button "Click here" [t/text: f/text]
]
view append append [] txt_btn txt_btn
The problem arises as you refer to a named element in your block. But a word can not point to more than one element of the repeated elements, therefore the usage of compose in the complete solution in order to create unique names.
Maybe there is a bug in Red because I thought compose/deep would also do parentheses deep inside and not need more compose –

grayt_autoStartup = true,

According to http://www.webspellchecker.net/samples/grayt-ckeditor-plugin.html
the statement CKEDITOR.config.grayt_autoStartup = true; should activate "GrammarAsYouType (GRAYT) for CKEditor 4+" grammer service on the editor
Their demo code did not even show the spelling button on my local test.
The code from http://sdk.ckeditor.com/samples/spellchecker.html did show the spelling options but not grammer.
Tried to add to the config:"grayt_autoStartup = true," like the "scayt_autoStartup: true," works, but then the entire UI was gone and no spell or grammar check.
Any one has a spelling AND grammar working in a local deployment?
Thanks in advance
You are right - GRAYT for CKEditor can be started like this:
grayt_autoStartup: true
For adding spelling button to CKEditor UI you need the following:
CKEDITOR.config.toolbar = [{
name: 'editing',
items: ['Scayt']
}];
There is no separate button for GRAYT. So you will have button only for SCAYT.
jsfiddle: https://jsfiddle.net/jalners/j4ytgb2v/

How I make a pushbutton invisible in a GUI?

I want to play my wav on percussion background image area with my pushbutton, so i need my pushbutton invisible on my figure window.
My script:
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
[s,fs]=wavread('filename.wav');
sound(s,fs);
Thankyou..
To make your push button invisible when you click it, set visibleto off in the callback function
set(hObject, 'Visible', 'off')
To make it invisible from other parts/functions in your GUI, just replace hObject with the handle of your push button.
Update:
You could make a clickable image and play different sounds for different click positions. Use the callback 'ButtonDownFcn' to trigger at a click event in the image. You can the retrive the position of the click by using the axes property 'CurrentPoint'. This return as 2x3 matrix with x-y-z projected coordinates. But as you are using a 2D plot you could simply pick the first 2 values, read more here.
Then use the x/y coordinates to find out what in the image that the user clicked on and play the sound for that.
A simple example:
% Draw an image
figure()
imHandle = image(imread(figPath));
% Set callback function (target function could have any name)
set(imHandle,'ButtonDownFcn', #ImgClickCB);
And the callback function (displays the x and y coord.)
function ImgClickCB(hObject, ~)
clickPoint = get( get(hObject,'Parent'), 'CurrentPoint');
fprintf('Clicked at x: %0.f y: %0.f \n', clickPoint(1,1), clickPoint(1,2));
The following example hides, and shows a pushbutton.
I created a sample, without using guide.
You can copy and paste the code into Matlab m file for execution.
Creating GUI without guide tool, better suit Stack Overflow site, because there is no need to attach a fig file.
You better use guide tool, because creating a GUI without it is complicated.
The following code sample hide (and show) pushbutton:
%TestNoGuideHideButton.m
%Create GUI with two buttons, without using GUIDE.
function TestNoGuideHideButton()
%Create figure.
h.fig = figure('position', [800 400 260 80]);
%Add button, with callback function Button1
h.buttonOne = uicontrol('style', 'pushbutton',...
'position',[10 20 100 40], ...
'string' , 'Button1', ...
'callback', {#Button1});
%Add button, with callback function hideButton
h.buttonTwo = uicontrol('style', 'pushbutton', ...
'position',[150 20 100 40], ...
'string' , 'Hide Button1', ...
'callback', {#hideButton});
function Button1(hObject, eventdata)
%Modify color of Button1 to random color.
set(h.buttonOne, 'BackgroundColor', rand(1, 3));
end
function hideButton(hObject, eventdata)
is_visible = isequal(get(h.buttonOne, 'Visible'), 'on');
if (is_visible)
%Hide buttonOne if Visible.
set(h.buttonOne, 'Visible', 'off');
set(h.buttonTwo, 'string', 'Show Button1'); %Replace string.
else
%Restore buttonOne if hidden.
set(h.buttonOne, 'Visible', 'on');
set(h.buttonTwo, 'string', 'Hide Button1'); %Replace string.
end
end
end
For the problem you described above, you obviously can't add a button for showing and hiding the other button.
You can restore the button when playing finishes.
You can also add a callback function for the background figure (look for WindowButtonDownFcn in guide).
Pressing anywhere on the figure, triggers the callback, were you can restore the hidden button.
You might want to have a look at this blog entry where I discussed how to manipulate the CData property of uicontrols.
I've added some code below to show a simple example:
f = figure(); % create a figure with an axes on it
pb = uicontrol('Style','checkbox', 'Units','pixels', 'Position',[10 10 300 200], ...
'Callback',#(a,b)msgbox('play clown!'));
% read some data
data = load ( 'clown' );
% extract out the image
img = data.X;
% convert image to RGB for displaying on checkbox
img = ind2rgb(img,colormap(f));
% Set the cdata property of the checkbox to be the image of interest
set(pb, 'CData', img )
The above code creates a figure with an image of a clown which you can click on (this could be your drum). The "button" stays there the whole time you don't need to make it invisible
Note: I use a checkbox instead of a button -> because sometimes a button can have a "border" when its in focus which can detract from the image whereas a checkbox doesn't.
I've copied the image produced below (after I clicked on the button):

Resources