Is there a way to center gui buttons and fields in Rebol? - user-interface

Spent hours trying to figure this out and still haven't got it. None of the documentation mentions anything about it. Is this something rebol just can't do without manually having to rearrange everything with origin?
Perhaps I'm just expecting too much?
edit: well I've discovered a hack: indent num, then indent -num on the next line . Out of all the spectacular features of this language why couldn't they have just added a simple command like center?

There is a CENTER-FACE function you can reuse to align faces, but unfortunately it doesn't work very well from my experience. Here is a simpler replacement version that should do the trick:
center-face: func [face [object!] parent [object!]][
face/offset: parent/size - face/size / 2
]
Here is a usage example:
lay: layout [
size 300x300
b: button "Hello World"
]
center-face b lay
view lay

First off, VID is not Rebol, but a demonstration dialect written by the author, Carl Sassenrath, to demonstrate how interfaces could be dialected in Rebol. There are others including RebGUI ( http://www.dobeash.com/rebgui.html ) though I suspect there isn't a way to center buttons there either as neither author considered it important.
You can also use PAD to align the cursor close to the center of the layout.

We can't center or align stuff based on the window itself because controls do not have any way to refer to their parent face until AFTER the parent has had 'SHOW called on it.
face/parent-face isn't set until the parent has been shown. So in normal VID you need to tweak the gui just after the initial layout & view has been done.
here is a little script which shows how to center any face, after its been shown at least once.
view/new is used to delay event handling, in order to modify the layout.
rebol []
center: func [face][
face/offset/x: (face/parent-face/size/x / 2) - (face/size/x / 2)
show face
]
view/new layout [
across
t: h1 "This is a centered title!"
return
button "1"
button "2"
button "3"
button "4"
]
center t
do-events

Related

NSButton wrap title dynamically

What I want to accomplish:
I need a checkbox with a title text that dynamically wraps and breaks on multiple lines depending on a dynamic width established by the parent view. I need a solution that I can use in IB and that will display there as it's shown at runtime. I'm using XCode 13.1, working in a XIB-File targetting MacOS.
What I'm doing:
I create an NSButton in IB. In the attributes inspector I set its style to Check, under "Control" I choose Word Wrap for "Line Break" and finally I set a very long text as the title such as Asd Asd Asd lit tle words and many of them asd asd lit tle ones.
What's happening:
When setting up the button as described above (case 1) and shrinking its width, it will be displayed - in IB and at runtime - like this:
When manually adding a line break to the title as suggested in this similar question by pressing Option + Enter (case 2, here after "them") the title starts wrapping correctly and all the other necessary breaks are generated:
However this solution is not applicable for my case since it only works for a static width, but my checkboxes need to adjust their width dynamically as described above.
Without that additional manual line break it's most interesting that apparently the checkbox is already reacting and changing its position according to the new wrapped height of the title while the title text itself is just clipped by the bounds of the control instead of being displayed in a wrapped fashion.
What I'd expect:
I'd expect the title to wrap in case 1. Since it doesn't: Is this a bug or a feature? How can I make case 1 work and get the title to wrap dynamically depending on its length and the width of the button? Do I just need to set another attribute in the inspector I missed so far? Or is there only a programmatic solution?
To answer the question why I don't use an appropriately short label: Don't ask me, I'm just a developer following specs & reqs and unfortunately I don't have a saying on what would be a good length of text here.
The credits for this answer goes to #Willeke's comment: "AppKit doesn't support multiline checkboxes." The interesting behaviour of the checkbox in case 1 suggesting otherwise seems to be just a glitch or bug.
What I ended up with: I opted for a workaround. I'm placing a checkbox-button (with Image Position "Image only" in IB) right beside a multiline-label, putting both in a custom view, adding the necessary constraints. With a few positioning adjustments I know have a solution that looks exactly like a singleline checkbox, that I can copy-paste in IB and that is solved by Autolayout - in IB and at runtime - without any additional code.

How to grab the scrolling amount in one window?

This is the first step to scroll two windows simulteneously, the second step is to find a way to apply that amount to the other program. But I really don't know where to start, all I see in from Google is about modifying the behavior of the scroll of the mouse, not the scrolling amount in one window. Advantages of using this instead of listening to the keys:
Scrolling will be seamless since the other program are scrolled in the background
Clicking on the scrollbar works
Different scrolling speeds don't affect the comparison
Moving lines in text editors won't scroll pages in PDF viewers
I can tell you what I would do, but it's not going to be fun...
Assuming the text is roughly evenly distributed (which it might not be between two languages like that, and two windows with different text sizes and widths, really consider this carefully before you do the work), then the goal is to force both scroll bars to be at the same percent relative to their whole. So what you need to do is write a function to determine what percent each scroll bar is at. I would screen capture both windows and crop out the important parts of the scroll bar like this:
Specifically the up and down buttons, the top of the scroll handle, the bottom of the scroll handle. Save them in their own files. Do it for both windows in case they draw their scroll bars a little differently.
Now the tricky part. Write a function that does the following: imagesearch for the top button within rightmost 25 pixels or of the specified window. Same for the bottom button. Same for the top of the handle. Same for the bottom of the handle. Use this to determine where your window is.
SetTitleMatchMode, 2 ; so it matches the end of the title
WinGetPos , X, Y, Width, Height, LibreOffice Writer ;exact substring of window name required
Use something like this to find the scroll bar parts.
CoordMode, Pixel , Screen ;so image search searches entire screen
barwidth = 25 ; make sure it's more than the bar is wide.
ImageSearch, TopButtonX, TopButtonY, X+Width-barwidth , Y, X+Width, Y+Height, TopButton.bmp ; no jpg, fuzzy edges make searches fail
Then do some math, something like:
TopButtonY := TopButtonY+TopButtonImageHeight ; because we only care about the position of the bottom of the button.
BottomHandleY := BottomHandleY+BottomHandleImageHeight ; because we only care about where the bottom of the handle is.
HandleHeight := TopHandleY - BottomHandleY ; how tall the scroll handle is
TotalHeight := TopButtonY - BottomButtonY - HandleHeight ;how tall the scroll field is
HandleOffset := TopHandleY - TopButtonY ;how far it is from the top
HandlePercent := HandleOffset / TotalHeight ; the part we care about. return this value
With a function like that, you can know how scrolled each window is. All that's left is to send the scroll commands. There's a few choices.
; ControlSend , Control, Keys, LibreOffice Writer
ControlSend , Control, {Pgdown}, LibreOffice Writer ; or {Pgup}
ControlSend , Control, {WheelUp}, LibreOffice Writer ; or {wheeldown}
ControlSend , Control, {Up}, LibreOffice Writer ; or {down}
If it lets you move the caret with up/down arrows while the window is inactive, that is probably the most precise option, even if it takes a bit longer. The fastest most precise way is to simulate a click drag also using control send. To use ControlSend you need to figure out which control you're working on. WindowSpy can help you with that.
So first: Find the scroll positions of both windows. Second determine which window is active. Third, nudge the inactive window in the correct direction. Repeat until they're within a certain tolerance range (otherwise it will bounce up and down endlessly).
I can't emphasize this enough, but please make sure that getting the scroll bars in approximately the same positions is sufficiently close before even attempting this. If it isn't, you will have wasted a lot of time fiddling with it. Keep in mind it will be less and less accurate the longer the text is.
If it is an option, I would definitely consider copying the contents of both windows into a program that gives you more access to the controls (or better one that is specialized for this purpose). If you had more access, you could use the paragraph breaks to line up the texts with far more precision.
If you really just want to see both texts side by side (and the paragraphs do line up), you could find a text editor that tells you information like this:
If autohotkey will let you read the text of that information, you can copy the PDF into autohotkey's memory (separated by line) and use autohotkey to show only the corresponding paragraph of the PDF as you move around in the editable document.
Hope something I said helps, good luck.

What's wrong with my PyQt animation?

So I've got a pair of buttons, one with a label, the other with a "delete" icon. The delete button will eventually delete some files, but right now I'm playing with the UI. The buttons are in a GridLayout with a spacer between them. I figure if I shrink the size of the button with the label, it'll "compress" as the spacer enlarges to fill the space. At least that's how it works in Qt Designer.
My button size definition is very simple:
ui.labelbutton.setMaximumSize(QSize(315, 50))
So I figure the animation should be relatively simple as well. I followed the format of another answer I found here, and I've got this:
def anim(self):
animation = QPropertyAnimation(self, b'maximumSize')
animation.setDuration(3000)
animation.startValue(QSize(315, 50))
animation.endValue(QSize(10, 50))
animation.start()
self.animation = animation
I pass it one of the label buttons (after extracting it from the layout - it's dynamically built). And I get an error:
animation.startValue(QSize(315, 50))
TypeError: startValue(self): too many arguments
According to all the examples and documentation I can find, that should be correct - a QSize is really just one argument, isn't it?
Anyone have a guess at how I can add some pointless eye candy to my application? Thanks.

Xamarin Forms - Why Is LineBreakMode TailTruncation Causing Word Wrap

In a Xamarin Forms project (C# code, not XAML), I have a some nested horizontal stacklayouts that look like this:
Notice there's a "Declined:" Label, then a quantity Label (4), and then a reason code Label ("Can't Find"). I have set the reason code Label to a LineBreakMode of LineBreakMode.TailTruncation. I would expect that when the label gets too long to fit on the line, it would truncate it with ellipses. It does. However, it doesn't do it gracefully - it causes things to be squished and to word wrap, like this:
I have set the "Declined:" Label to LineBreakMode.NoWrap, and you'll notice the last "d" in "Declined" is cut off". I haven't set any LineBreakMode on the "Ordered" and "Picked" Labels, and you'll notice those word wrap. Why is this happening, and how can I fix it?
Does it look normal again when you rotate the device or if you call ForceLayout() on the parent element to all of those nested StackLayouts?
I have noticed that sometimes I must do that to force a redraw or layout pass on certain devices (usually is it only needed on one platforms or another as opposed to all platforms).
If that doesn't work, I would suggest using Grid if that is possible in your situation. That is what I tend to do when I run into elements sitting on top of each other like this. I am not sure why it happens but Grid never fails me. Grid seems to be much more strict about spacing and does not let things bleed over like that

AutoIt ControlCommand is not working as expected

I'm using AutoIt to try and make a little hotkey application to work with Windows Journal so I can quickly select different colors.
It seems I'm very close and yet very far to getting the desired result. I've used the AutoIt tool to find the CommandID of the toolbar and the ID of the colors. Here is my code:
ControlCommand("[CLASS:JournalApp]","",113,"SendCommandID", 40178)
My problem is that the color will not be selected. It will be selected to the degree that the color will have the "selection" brackets around it, but the color that I draw with will still be the last color I've selected.
So I tried messing around and found that this code:
ControlCommand("[CLASS:JournalApp]","",113,"Check","")
It will indeed select the color, but it will only select the light blue color. I don't know why, but that is the color that is always being selected. I have not found a way to combine the selecting ability of "SendCommandID" with the checking ability of "Check"
Also, it is a ToolbarWin32 Control.
I figured it out myself.
Here's what I've learned:
ControlCommand("[CLASS:JournalApp]","",113,"Check","")
Has a serious weakness in that it there is no way to specify which button will be checked. At first it seemed to be random, but after a while of playing around I noticed that it did it at a specific coordinate relative to the client window. Why? I have no idea. But at least it's not random.
ControlCommand("[CLASS:JournalApp]","",113,"SendCommandID", 40178)
Has a weakness in that, while on the surface it appears to have successfully clicked the button. The button's function is not actually executed. For my specific circumstance, the color of the pen did not change after I used this, though it appeared to click on the button.
Here's my solution(s):
I looked around and found that AutoIt has a library specifically for dealing with ToolBarWin32 Classes. This is the library from GuiToolbar.au3. With this I found that I was able to do a few things. One, was that I could send clicks to the buttons and change the state of the buttons even. I found that changing the state of the buttons did nothing in relation to triggering an event and the clicking worked, but it had the weakness that it caused the mouse to flinch. This did not work because my pen was near my tablet as that has priority of mouse movement. So I had to raise my pen away from my tablet in order to use the hotkeys--not very convenient. Here was my code for that solution:
if WinActive("[CLASS:JournalApp]") Then
WinActivate("[CLASS:ToolbarWindow32; INSTANCE:2]", "")
$cmdId = "401"&$hotKeys[$key-1+$shift]
If $cmdId < 40172 or $cmdId > 40188 Then
Return
EndIf
$hWnd = ControlGetHandle("[CLASS:JournalApp]", "", 113)
_GUICtrlToolbar_ClickButton($hWnd, $cmdId)
EndIf
What I found after was that AutoIt's native ControlClick() was a lot more useful in that it didn't cause the mouse to flinch whatsoever. It triggered the mouseclick event directly. So that in combination with a nice command from the toolbar library made for a much cleaner solution. Here it is:
if WinActive("[CLASS:JournalApp]") Then
WinActivate("[CLASS:ToolbarWindow32; INSTANCE:2]", "")
$cmdId = "401"&$hotKeys[$key-1+$shift]
If $cmdId < 40172 or $cmdId > 40188 Then
Return
EndIf
ConsoleWrite($hotKeys[$key-1])
$hWnd = ControlGetHandle("[CLASS:JournalApp]", "", 113)
;get the coords of the button and control send a click
local $btnCoords= _GUICtrlToolbar_GetButtonRect($hWnd, $cmdId)
ControlClick("[CLASS:JournalApp]", "", "[CLASS:ToolbarWindow32; INSTANCE:2]","left",1,$btnCoords[0]+2,$btnCoords[1]+2)
EndIf

Resources