Shoes problems: clipboard and scroll bar - scrollbar

The code below has (at least) two problems: the Copy button doesn't update the clipboard, and the edit_box doesn't show a vertical scroll bar when it should.
Shoes.app (:title => "Test", :width => 1000, :height => 600) do
background "#DFA"
stack :margin => 30 do
flow do
button "Paste" do
#sql.text = clipboard
end
button "Copy", :margin_left => 15 do
clipboard = #sql.text
alert(#sql.text.length.to_s + " characters copied to clipboard.")
end
end
stack :margin_top => 10, :width => "100%", :height => 500, :scroll => true do
#sql = edit_box :width => "100%", :height => "100%"
end
end
end
The Paste button correctly pastes the clipboard contents into the edit_box. If you make changes, then click Copy, the alert message displays the correct number of characters. If you then click Paste again, the original clipboard contents are pasted. The Copy button never correctly updates the clipboard.
Also, if you generate more lines than fit the edit_box, either by editing or pasting, no scroll bar ever appears.
Any help on these two issues will be much appreciated. My environment is Windows XP if that helps.
UPDATE WITH ANSWERS: Thanks to #Pesto for answering the clipboard question. It turns out that qualifying clipboard with either app. or self. works as expected in both the Paste and Copy buttons.
After digging deeper into the scrollbar issue, I think I understand why the edit_box doesn't show a scrollbar. The scrollbar in Shoes applies only to slots (stack and flow), and not to individual elements like edit_box. The edit_box height is specified in such a way as to always fit within the enclosing stack, so the stack never needs a scrollbar. This led me to a work-around that is not ideal, but is acceptable for my application. Simply change the edit_box height to a larger-than-necessary value such as "10000px" and the scrollbar appears. Unfortunately, it's there whether needed or not, but that's better than no scrollbar. I'm sure that some additional tinkering can dynamically change the edit_box height to exactly fit the contents, so that the scrollbar will appear only when needed.

First of all, the easy one: change the line in the Copy button to app.clipboard = #sql.text.
Second, as far as the scrollbar goes, this is a known issue on Windows XP. I don't see it listed in the bug reports on github, but the latest version (r1229) still doesn't have a scrollbar.

Related

Do not make the width of the button proportionnel to the width of the popup window

I want to make a button in a popup window as Script Lab as follows. Note that, in Script Lab, the width of the button is enough to hold the sentence in one line, even though the popup window is not very wide:
I almost use the same code as ScriptLab:
import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
... ...
return (
<div style={{ height: '100vh', display: 'flex', flexDirection: 'column'}}>
<PrimaryButton
style={{ margin: 'auto' }}
text="Open link in new window"
// tslint:disable-next-line: jsx-no-lambda
onClick={() => {
window.open(this.props.url);
}}
/>
</div>
);
Here is my result, where the width of the button is proportionnel to the width of the popup window. As a consequence, the sentence needs to be displayed in 2 rows, which is not what I want.
Does anyone know how to amend the code to get the effect like Script Lab?
Edit 1:
I have made a sandbox: https://codesandbox.io/s/relaxed-feather-i6jz6?file=/src/App.js
Now, the problem is, if we Open In New Window and open https://i6jz6.csb.app/ in a new browser tab several times, we may see a little adjustment of the font of the text in the button. Does anyone know how to avoid that?
On button width:
In order to not have the width of the button grow proportionately with the container you can enforce the width: auto on the button. This way it will only be as wide as it needs to be to contain the text. Value auto is also better than having a fixed width, because it can automatically wrap the text if the popup becomes too narrow to display the text in one line (with fixed width your button would overflow instead - which looks really bad).
On font adjustments
For the font adjustments you experience - this is a very common thing on web and it even has its own name - FOUT (Flash of Unstyled Text). It happens when you use custom fonts on the page, because these are files like any other and so they take some time to download. Browsers prefer displaying the content as early as possible (even without custom fonts loaded) to displaying the perfect content (by waiting on all resources) with some speed penalty.
The only way (at least that I know) to completely avoid FOUT is to use system fonts instead of custom fonts (github does that for example).
If that's not an option, you can minimize the FOUT by caching the fonts on client machines for long times. This way they will experience the flash briefly on the first visit, but not on subsequent ones.
You can also try to minimize the FOUT by telling the browser to try to preload the font files that will be needed for the page (part of the reason why FOUT happens is that browser discovers the fonts very late) https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
Set a fixed width to the button.Setting a fixed width will make it unproportional to the width of the pop-up window.
width:280px;
Second Option: If you use min-width, the button width will decrease to a point.
Third Option: If you use max-width, the button width will increase upto a point.
Fourth Option: You can also use '#media' queries to customize the width according to size of the screen.
You don't want the button's text to wrap, so you'll need to change the font size, which you can do when you find that the button's height increases when the text wraps. I suggest that you create a invisible, but not 'display: none', possibly 'off-screen' version of the button so that the real button's font is changed after you know the right size is needed. Alternatively, what about an image or glyph instead of text, and a Title for the button text?

How to clip areas drawn by `:layout` methods in awesome-wm?

This is a follow-up to How to make mouse events propagate to widgets in `scroll` containers?
TL;DR:
The :layout method I implemented makes the widget draw all over the other widgets (see pictures below). How can I constrain where the :layout method will draw my widgets and where it will allow me to interact with the children?
Longer version:
So I ended up patching the scroll container and what I basically did was that I implemented a :layout method, based on the offset calculations that were already made in the original scroll container code.
This is basically what I did (I'll only put the relevant parts here):
-- this function emits signals `self._private.fps` times a second
local _need_scroll_redraw = function(self)
if not self._private.paused and not self._private.scroll_timer then
self._private.scroll_timer = timer.start_new(1 / self._private.fps, function()
self._private.scroll_timer = nil
self:emit_signal("widget::redraw_needed")
self:emit_signal("widget::layout_changed") -- this is the only
-- line that I added
-- to this function
end)
end
end
local function calculate_info(self, context, width, height)
-- this is a longer function, but in summary here we calculate the
-- ideal size that the child would like to be, we see if the child
-- is bigger than the space we have for drawing, and if it is,
-- we calculate offsets (and we call `_need_scroll_redraw` here)
-- so we later know where and how often to `:draw` and `:fit` it
end
function scroll:fit(context, width, height)
local info = calculate_info(self, context, width, height)
return info.fit_width, info.fit_height
end
function scroll:layout(context, width, height)
local result = {}
local i = calculate_info(self, context, width, height)
table.insert(result, base.place_widget_at(
self._private.widget, i.first_x, i.first_y, i.surface_width, i.surface_height
))
return result
end
-- Also, there was a `:draw` method, but I took it out entirely since
-- if I add the `:layout` method, things get drawn just fine
-- P.S: I also tried to implement what was in the `:draw` method, inside
-- the `:layout` method, so that it'll clip properly. I also tried that idea
-- with the `:before_draw_children` and `:after_draw_children` methods
-- but since I don't know how to use cairo, god knows what I wrote there,
-- but it didn't work
With the default scroll widget, my widget looks like this, but nothing I click on works:
But with the changes I made above, the widget with the rows does scroll, and I can click on each child just fine and have it react, it's just that it draws everything outside of its boundaries, and I can also click on stuff that's outside of the boundaries:
So my question is: how would I go about restricting what the :layout method displays, to have it work the way the default scroll layout works, but still be able to interact with the children?
Untested, but I guess:
function scroll:before_draw_children(context, cr, width, height)
cr:rectangle(0, 0, width, height)
cr:clip()
end
This takes the rectangle describing the size of the scroll widget and clips all children to it, meaning that they cannot draw outside of the scroll widget.
Note that this is only prevents the drawing of the child widgets. It does not make awesomeWM "forget about them". What I mean with that is: You can still click on the where the widget would be if it were visible. The click will still be handled by the widget. Only the actual drawing of the child widget is prevented.
The above is why I asked in your original question whether you want just this one widget to be scrolled, without anything next to it. Because if the scroll widget covers the whole wibox, this whole class of issues just goes away.
And no, as far as I know / see, there is no way to prevent the not-drawn widgets from receiving button clicks.

Detect when NSWindow's "Show Tab Bar" gets enabled

I have a height-limited window: It cannot grow above a certain height (based on its current content), but can be made smaller (in which case I'll add a vertical scrollbar).
I limit the maximum height with a NSLayoutConstraint.
Now, if the user enables tabbed windowing by checking the menu command View -> Show Tab Bar, the window's contents get moved down in order to make room for the tab bar but the entire window's height remains the same, which effectively leads to the content being "squished", so that my current code decides to add the vertical scrollbar, as if the user just reduced the window height manually.
I rather have the window grow with the bar tab instead. How can I accomplish this?
There seems to be no event or notification that would inform me when the Tab Bar got enabled.
What's a clean way to detect the activation of the Tab Bar then, so that I can grow my window height along with it?
I poked around with KVO and found that I could watch NSWindow's tabbedWindows property for this purpose (tested on 10.13.6).
In the ViewController's viewWillAppear:
if ([self.view.window respondsToSelector:#selector(tabbedWindows)]) {
[self.view.window addObserver:self forKeyPath:#"tabbedWindows" options:0 context:nil];
}
And then handle the change:
-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(id)change context:(void*)context {
// ... adjust my window's height
}
This may not be reliable, though, i.e. I found no documentation that guarantees that this will work in the future and is not just an accidental side effect.

Center buttons in dialog created with "gtk_dialog_new_with_buttons"

I am writing a Gtk application and I am having troubles centering some buttons.
I created a popup window in this way:
dialog = gtk_dialog_new_with_buttons ("Add element",
GTK_WINDOW(gElems->window),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
"OK",
GTK_RESPONSE_ACCEPT,
"Cancel",
GTK_RESPONSE_REJECT,
NULL);
Everything is ok, except for the OK and Cancel buttons, which are aligned to the right end of the popup window, while I would like them to be centered (as you can see from the picture).
Is there a way to do so without using additional containers to store the buttons?
You can align the buttons in the middle
buttons_container = gtk_dialog_get_action_area (dialog)
g_object_set_property (G_OBJECT (buttons_container), "halign", GTK_ALIGN_CENTER)
and voila.....
If you want to change the container, you also can, but that's not what you want, really
Regarding luciomrx answer: It is needed to pass a gvalue, otherwise you will get a compile warning and a runtime crash:
GValue val = G_VALUE_INIT;
g_value_init (&val, G_TYPE_ENUM);
g_value_set_enum (&val, GTK_ALIGN_CENTER);
buttons_container = gtk_dialog_get_action_area (dialog);
g_object_set_property (G_OBJECT (gtk_dialog_get_action_area (dialog)), "halign", &val);
Even Simpler, you can just use gtk_widget_set_halign, which accepts an enum:
gtk_widget_set_halign (gtk_dialog_get_action_area (dialog), GTK_ALIGN_CENTER);
Edit: I just realized that gtk_dialog_get_action_area anyhow is deprecated in gtk3 .. so a different sulution should be found.

Init QListWidget to show its all content (with no scroll bars)

I was playing with the Config Dialog Example, all was fine. Then I changed something in the right part of the dialog.
Then I found the contentsWidget (QListWidget) in the left part of the dialog became smaller and showed the scroll bars (both Horizontal and Vertical).
I want the QListWidget to show all its content so that no scroll bars are needed.
All items are added at the beginning and fixed. No dynamic.
I guess there is a simply method to let the QListWidget expand to show all its content at the beginning.
Could anyone help me and tell me the magic word?
Here is the code:
contentsWidget = new QListWidget;
contentsWidget->setViewMode(QListView::IconMode);
contentsWidget->setIconSize(QSize(96, 84));
contentsWidget->setMovement(QListView::Static);
contentsWidget->setMaximumWidth(128);
contentsWidget->setSpacing(12);
//contentsWidget->setMinimumWidth(contentsWidget->sizeHintForColumn(0));
//contentsWidget->setMaximumWidth(contentsWidget->sizeHintForColumn(0));
//contentsWidget->adjustSize();
//qDebug()<<contentsWidget->sizeHintForColumn(0);
createIcons();
contentsWidget->setCurrentRow(0);
QHBoxLayout *horizontalLayout = new QHBoxLayout;
horizontalLayout->addWidget(contentsWidget);
horizontalLayout->addWidget(pagesWidget, 1);
I tried contentsWidget->sizeHintForColumn(0), but it didn't work. It was 0. I tried some other methods but nothing worked.
I think you should try:
contentsWidget->setMinimumWidth(128);
This will ensure that no matters what, the size of contentsWidget will always be at least 128, hence large enough to contains the icons.

Resources