I would like to ask about proper way to split following screens in ALV:
1st screen with type CL_GUI_ALV_GRID
2nd screen is subscreen with Tab strip control
Using docker there are issues with resizing of screen during the runtime. I am not able to provide ratio for both screen.
Is there a way to use CL_GUI_SPLITTER_CONTAINER also for the screen with Tab strip control ?
Thank you !
The following code reacts to a change of the window height. It does not react to a window width, that's a limit of Dynpro, so most of time it will react to Windows buttons minimize and restore, unless the window is the exact half left or half right of the monitor (combined keys Windows+Left and Windows+Right). SY-SCOLS and SY-SROWS are the only way I know to get the window size when a dynpro screen is displayed, but probably there are other ways.
DATA go_docking TYPE REF TO cl_gui_docking_container.
DATA ok_code TYPE syucomm.
DATA ratio TYPE i VALUE 70.
DATA pixels_by_sy_scol TYPE p DECIMALS 2.
CALL SCREEN 100.
MODULE pbo OUTPUT.
IF go_docking IS INITIAL.
CREATE OBJECT go_docking
EXPORTING
repid = sy-repid
dynnr = sy-dynnr
side = cl_gui_docking_container=>dock_at_left
ratio = ratio.
go_docking->get_extension( IMPORTING extension = DATA(extension) ).
cl_gui_cfw=>flush( ). " to calculate the extension (by default in pixels)
pixels_by_sy_scol = extension * 100 / ratio / sy-scols.
ELSE.
go_docking->set_extension( sy-scols * pixels_by_sy_scol * ratio / 100 ).
ENDIF.
ENDMODULE.
Related
I'm working on a desktop application for windows using PyQt and Qt creator.
What I want
I want to display messages to the user only when the user gave an input. I also wanted the message to draw the eye, so I'm going for the following animated solution:
A frame that's hidden when not required (with height = 0 and width = the app's width), 'grows' from the bottom of the app when needed, stays visible for 5-6 seconds, then retracts back to the bottom.
The app kind of looks like this without the message:
And kind of like this when the message IS displayed (note how the bottom gray element is 'covered' by the message):
What I tried
So the way I did this was to create what I called "footer frame", which contains another frame that I call "message frame". The message frame contains a label that will hold, in time, the message for the user. Everything has pre-determined height, so to hide the whole thing I set the message frame to have a maximum height of 0.
So for the 'growing' animation I animated the message frame's maximumHeight property.
The current problem
THING IS - since I wanted the app to be responsive I put everything in layouts... and because of that, whenever the message is displayed, the rest of the components are 'compressed' in height.
kind of like this (note how the bottom gray element is not covered by the message, but all the elements' heights shrink a little):
Instead, I wanted the messsage to 'cover' whatever is located under the message's coordinates.
I tried to animate the geometry of the message frame, but nothing really happened - probably because the minimum height is still 0. So I tried to change the minimum height right before the animation begins; But that led to that compression again.
Tried to do the same with the footer frame, with the same results.
My question is : What is the best / preferred way of achieving the result I intend with Qt?
Layout managers always try to show all widgets they're managing. If you want a widget to overlap others, you cannot put it inside a layout, you just create the widget with a parent, and that parent will probably be the widget containing the layout above or the top level window.
This cannot be done in Designer/Creator, as it's assumed that once a layout has been set for a parent widget, all child widgets will be managed by that layout. The only solution is to do this programmatically.
In the following example I'm assuming a QMainWindow is used, so the reference parent widget is actually the central widget, not the QMainWindow: that's because the alert should not cover other widgets that are part of a main window's layout, like the status bar or a bottom placed tool bar or dock).
The animation is actually a QSequentialAnimationGroup that shows the rectangle, waits a few seconds, and hides it again. Since the window could be resized while the animation is running, a helper function is used to properly update the start and end values of the warning and eventually update the geometry when in the "paused" state (which is actually a QPauseAnimation); in order to do so, an event filter is installed on the central widget.
from random import randrange
from PyQt5 import QtCore, QtWidgets, uic
class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi('overlay.ui', self)
self.alerts = []
self.centralWidget().installEventFilter(self)
self.pushButton.clicked.connect(self.showAlert)
QtCore.QTimer.singleShot(2000, self.showAlert)
def showAlert(self, message=None, timeout=250):
# create an alert that is a child of the central widget
alert = QtWidgets.QLabel(message or 'Some message to the user',
self.centralWidget(), wordWrap=True,
alignment=QtCore.Qt.AlignCenter,
styleSheet='background: rgb({}, {}, {});'.format(
randrange(192, 255), randrange(192, 255), randrange(192, 255)))
self.alerts.append(alert)
alert.animation = QtCore.QSequentialAnimationGroup(alert)
alert.animation.addAnimation(QtCore.QPropertyAnimation(
alert, b'geometry', duration=timeout))
alert.animation.addAnimation(QtCore.QPauseAnimation(3000))
alert.animation.addAnimation(QtCore.QPropertyAnimation(
alert, b'geometry', duration=timeout))
# delete the alert when the animation finishes
def deleteLater():
self.alerts.remove(alert)
alert.deleteLater()
alert.animation.finished.connect(deleteLater)
# update all animations, including the new one; this is not very
# performant, as it also updates all existing alerts; it is
# just done for simplicity;
self.updateAnimations()
# set the start geometry of the alert, show it, and start
# the new animation
alert.setGeometry(alert.animation.animationAt(0).startValue())
alert.show()
alert.animation.start()
def updateAnimations(self):
width = self.centralWidget().width() - 20
y = self.centralWidget().height()
margin = self.fontMetrics().height() * 2
for alert in self.alerts:
height = alert.heightForWidth(width) + margin
startRect = QtCore.QRect(10, y, width, height)
endRect = startRect.translated(0, -height)
alert.animation.animationAt(0).setStartValue(startRect)
alert.animation.animationAt(0).setEndValue(endRect)
alert.animation.animationAt(2).setStartValue(endRect)
alert.animation.animationAt(2).setEndValue(startRect)
def eventFilter(self, obj, event):
if obj == self.centralWidget() and event.type() == event.Resize and self.alerts:
self.updateAnimations()
for alert in self.alerts:
ani = alert.animation
# if the animation is "paused", update the geometry
if isinstance(ani.currentAnimation(), QtCore.QPauseAnimation):
alert.setGeometry(ani.animationAt(0).endValue())
return super().eventFilter(obj, event)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec())
How to configure a shortcut key in awesome to toggle a client window vertical maximization to the left half of the screen (snap to left)?
Module awful.placement has an example that may help, but there is no mention on how to implement a toggle that would be able to maximize the client or restore it to its prior size and location.
Currently I have the following in rc.lua:
clientkeys = gears.table.join(
-- ...
awful.key({ modkey, "Mod1" }, "Left",
function (c)
-- Simulate Windows 7 'edge snap' (also called aero snap) feature
local f = awful.placement.scale + awful.placement.left + awful.placement.maximize_vertically
f(c.focus, {honor_workarea=true, to_percent = 0.5})
end ,
{description = "maximize vertically to the left half of screen", group = "client"})
)
Are you looking for awful.placement.restore? It seems to do be what you are looking for. However, the documentation says one has to "set[...] the right context argument" for this, but does not mention which one that is.
I think it should be scale since it is the first one in your chain, but I fail to see the logic in calling this chain "scale".
To turn that into a toggle, you can "invent" a new client property. Something like this: if c.my_toggle then print("a") else print("b") end c.my_toggle = not c.my_toggle. This way, the my_toggle property tracks which function you have to call.
Situation
I have a pop_up widget (say a textbox), which I can place arbitrarily on the screen by setting the properties x and y accordingly.
On the other hand I use the prompt, which is located in the default wibar.
I would like to place the pop_up widget directly below the prompt
Problem
I was not yet able to gather any useful information about the geometry of the prompt. With geometry I mean its x and y values together with its height and width. I solved the y-positioning by using the height of the wibar itself.
But I am stuck with x-positioning.
Is there a way to get the width of the widgets within the toolbar?
Notice
I read something about forced_width, but in this situation it sounds like a hack to me. So I would prefer to avoid forcing any widths.
I'm currently running awesome WM 4.2 on Fedora 26
Part of a problem is that "a" widget does not have a position and size since awesome allows widgets to be shown in multiple places at once. However, if we just ignore this problem, something like the following could work (to be honest: I did not test this):
function find_widget_in_wibox(wb, widget)
local function find_widget_in_hierarchy(h, widget)
if h:get_widget() == widget then
return h
end
local result
for _, ch in ipairs(h:get_children()) do
result = result or find_widget_in_hierarchy(ch, widget)
end
return result
end
local h = wb._drawable._widget_hierarchy
return h and find_widget_in_hierarchy(h, widget)
end
However, I have to warn you that the above could break in newer versions of awesome since it access non-public API (the part with wb._drawable._widget_hierarchy). There is a way to work with just the public API using :find_widgets(), but I am too lazy for that for now.
The above function gets the wibox.hierarchy instance representing a widget which allows to get the geometry of the prompt via something like the following (in the default config of awesome 4.2):
local s = screen.primary -- Pick a screen to work with
local h = find_widget_in_wibox(s.mywibox, s.mypromptbox)
local x, y, width, height = h:get_matrix_to_device()
:transform_rectangle(0, 0, h:get_size())
local geo = s.mywibox:geometry()
x, y = x + geo.x, y + geo.y
print(string.format("The widget is inside of the rectangle (%d, %d, %d, %d) on the screen", x, y, width, height)
Finally, note that the widget hierarchy is only updated during repaints. So, during startup the code above will fail to find the widget at all and right after something changed (e.g. you entered another character into the promptbox), the above will still "figure out" the old geometry.
I've an old desktop application developed in progress 4gl.There is a frame contained in a progress window now my task is to make the frame responsive ie based on the size of its container window the frame should resize dynamically.Is it possible in Progress any workaround will be appreciated.Thanks
Once the frame has been "realized" you cannot change its height or width.
Prior to that you can manipulate the geometry via the frame handle.
To change things after the frame has been displayed you will basically need to build a new frame to replace the old one.
I'll assume you don't own the source code. If your window hasn't been set as RESIZE, then there's really no luck.
Otherwise, I created this simple program, which should make it possible to manipulate the window and the frame inside it. Now remember: All fields will have to be manually repositioned inside the frame. You also might want to set session:suppress-warnings to YES before you get this running, because every time a widget doesn't fit the frame, OpenEdge will let you know about it. You might need to cycle all objects inside the frame's field-group, to make it happen. And remember to get fill-ins side-label-handle to move them too, otherwise the fill-in itself moves, but the text stays. It's a lot of work.
So without further ado, the code:
DEFINE VARIABLE hProgram AS HANDLE NO-UNDO.
DEFINE VARIABLE hWindow AS HANDLE NO-UNDO.
DEFINE VARIABLE hFrame AS HANDLE NO-UNDO.
run <ProgramNameGoesHere> persistent set hProgram.
run enable_UI in hProgram.
assign hWindow = hProgram:current-window
hFrame = hWindow:first-child.
/* Resize Variables */
DEFINE VARIABLE dWinXC AS DECIMAL NO-UNDO.
DEFINE VARIABLE dWinYC AS DECIMAL NO-UNDO.
/* /Resize Variables */
ON WINDOW-RESIZED OF hWindow
DO:
/* Defining a minimum size here */
if hWindow:width-chars < 74 or
hWindow:HEIGHT-CHARS < 22 then return no-apply.
run piResize.
END.
procedure piResize:
def var dXC AS DECIMAL NO-UNDO.
def var dYC AS DECIMAL NO-UNDO.
/**--------------------------------- Screen Size ----------------------------**/
assign dXC = dWinXC - hWindow:width-chars
dYC = dWinYC - hWindow:height-chars
dWinXC = hWindow:width-chars
dWinYC = hWindow:HEIGHT-CHARS
/**-------------------------- Objects on Screen -----------------------------**/
hFrame:width = hWindow :WIDTH
hFrame:height = hWindow :HEIGHT no-error.
/**-------------------------------- Frame Sizes -----------------------------**/
ASSIGN hFrame:width = hWindow:width
hFrame:height = hWindow:HEIGHT no-error.
end procedure.
wait-for 'close' of hProgram.
Now, I don't know if this does you any good, since you can't probably interfere with behavior at will. Notice the inclusion of a trigger overrides whatever was there before (since your window did not resize, I don't think it will harm it. But doing that for a widget that already has an event procedure will cause it to stop doing what it currently does (unless you can code it, but again I don't think you have the code).
I apologize for the code not being just the genius patch that Stack Overflow loves so much, but it's a complex issue. Hope it helps.
Oh, and this was made using Progress 10.2B. I imagine if your code is previous to v8, you might be out of luck.
I'm running on Windows 10, but using Delphi 7 (yes, I know it's quite old).
I want to use the system icons in Windows and have gone about this by defining a TImageList called SystemIcons which I initialize as follows:
var
fileInfo: TSHFileInfo;
begin
SystemIcons.Handle := ShGetFileInfo('', 0, fileInfo, SizeOf(fileInfo),
SHGFI_ICON or SHGFI_SMALLICON or SHGFI_SYSICONINDEX);
...
I have SystemIcons properties set statically as a TImageList component with width and height set to 16.
Elsewhere, I wish to retrieve an icon from this image list given a valid shell object's image index. Because these are "small system icons", I expect them to be 16x16. The result of calling GetSystemMetrics(SM_CYSMICON) yields 16. Oddly, the dimensions depend upon whether I retrieve them as a bitmap or an icon.
...
var
icon: TIcon;
bm: TBitmap;
begin
...
icon := TIcon.Create;
SystemIcons.GetIcon(imgIndex, icon);
bm := TBitmap.Create;
SystemIcons.GetBitmap(imgIndex, bm);
The imgIndex is correct and the same in both cases. The image retrieved is the same in each case, as expected. The dimensions of the bitmap (bm.Width and bm.Height) are also as expected: 16x16. However, the dimensions of the icon (icon.Width and icon.Height) are not. They are 32x32.
When I paint the icon on a canvas it appears as 16x16. So it's only its Height and Width values that appear incorrect. Very odd.
Why are these different?
The images are likely actually 32x32 to begin with.
Internally, TImageList.GetIcon() simply retrieves an HICON for the chosen image directly from the underlying Win32 ImageList API, using ImageList_GetIcon(), and assigns that to the TIcon.Handle property.
TImageList.GetBitmap(), on the other hand, is a bit different. It sizes the TBitmap to the dimensions of the TImageList (16x16), and then stretch draws the chosen image onto the TBitmap.Canvas using TImageList.Draw(), which in turn uses ImageList_DrawEx().