I have a BorderPane with a ScrollPane as the center element. It resizes automatically to fill the screen. Inside the ScrollPane is a HBox that has no content but is a drag-and-drop target. Therefore I want it to fill its parent ScrollPane.
What is the preferred way to do this?
What I have tried so far is overriding the ScrollPane.resize(...) method to resize the HBox but it seems rather complicated and unorthodox.
edit: To add some useful code to this, this is how I can workaround the problem, but I believe there has to be some better way to do this:
#Override
public void resize(double width, double height) {
super.resize(width, height);
double scrollBarHeight = 2;
double scrollBarWidth = 2;
for (final Node node : lookupAll(".scroll-bar")) {
if (node instanceof ScrollBar) {
ScrollBar sb = (ScrollBar) node;
if (sb.getOrientation() == Orientation.HORIZONTAL) {
System.out.println("horizontal scrollbar visible = " + sb.isVisible());
System.out.println("width = " + sb.getWidth());
System.out.println("height = " + sb.getHeight());
if(sb.isVisible()){
scrollBarHeight = sb.getHeight();
}
}
if (sb.getOrientation() == Orientation.VERTICAL) {
System.out.println("vertical scrollbar visible = " + sb.isVisible());
System.out.println("width = " + sb.getWidth());
System.out.println("height = " + sb.getHeight());
if(sb.isVisible()){
scrollBarWidth = sb.getWidth();
}
}
}
}
hBox.setPrefSize(width-scrollBarWidth, height-scrollBarHeight);
}
Code partly taken from here: How to access the Scrollbars of a ScrollPane
Try
ScrollPane scrollPane = new ScrollPane();
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);
without overriding the resize() method.
Setting the fitToHeight or fitToWidth attribute through XML or CSS:
FXML:
<ScrollPane fx:id="myScrollPane" fitToHeight="true" fitToWidth="true" />
CSS:
.my-scroll-pane {
-fx-fit-to-height: true;
-fx-fit-to-width: true;
}
Related
I was messing around with SWT (for a PropertyPage), and found a little 'bug'?
Basically, when I resize the shell so it is smaller than my controls, it will make a scrollBar visible, which works just as intended. Though if I resize my controls (which are all children of a single root of course), somehow one or more parents don't get updated of the change which results in some weird behavior.
When my controls grow in size, it basically grows out of the shell (not visible) while there is no Scrollbar made visible. If I resize the shell (smaller than the initial size), the ScrollBar will become visible, but only for the initial size instead of the full width.
When my controls shrink in size it won't 'pack' either parent, which means I can scroll beyond the reach of my controls into emptiness.
Maybe it's worth mentioning that for me only horizontal growing/shrinking is a problem, although I'm pretty sure the same problems are occurring for vertical resizing
My question was if there is a solution/workaround for this. I have tried calling Layout() and pack() on various parents and the shell itself, without success. Now I know there is a custom (sadly private) Layout type used by one of the parents of a property page (the PreferenceDialog#PageLayout). Maybe this behavior comes this implementation?
EDIT: on request an MCVE
I assume one knows how to setup for a propertyPage, so for the sake of clarity I have posted only the createContents method (overriden from org.eclipse.jface.preference.PreferencePage), and a few helper methods/fields which should recreate a setup where this behavior can be observed. Basically play around with hiding/unhiding columns, and make sure to re-open when you want a different initial childSize (to test both growing and shrinking)
// static so you can re-open a the property/preference page for different initial sizes.
private static boolean h1 = false;
private static boolean h2 = false;
private static boolean h3 = false;
private static boolean h4 = false;
private Composite root;
#Override
protected Control createContents(Composite parent)
{
// setup root
this.root = new Composite(parent, SWT.NONE);
this.root.setLayout(new GridLayout());
this.root.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
Table table = new Table(this.root, SWT.SINGLE | SWT.VIRTUAL | SWT.BORDER | SWT.FULL_SELECTION);
table.setHeaderVisible(true);
table.setLinesVisible(true);
table.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
TableColumn c1 = new TableColumn(table, SWT.LEFT);
c1.setMoveable(true);
c1.setText("column 1");
this.updateColumn(c1, h1);
TableColumn c2 = new TableColumn(table, SWT.LEFT);
c2.setMoveable(true);
c2.setText("column 2");
this.updateColumn(c2, h2);
TableColumn c3 = new TableColumn(table, SWT.LEFT);
c3.setMoveable(true);
c3.setText("column 3");
this.updateColumn(c3, h3);
TableColumn c4 = new TableColumn(table, SWT.LEFT);
c4.setMoveable(true);
c4.setText("column 4");
this.updateColumn(c4, h4);
Button hide1 = new Button(this.root, SWT.PUSH);
hide1.setText("Hide column 1");
hide1.addListener(SWT.Selection, E -> {
this.updateColumn(c1, h1 = !h1);
this.resize();
});
Button hide2 = new Button(this.root, SWT.PUSH);
hide2.setText("Hide column 2");
hide2.addListener(SWT.Selection, E -> {
this.updateColumn(c2, h2 = !h2);
this.resize();
});
Button hide3 = new Button(this.root, SWT.NONE);
hide3.setText("Hide column 3");
hide3.addListener(SWT.Selection, E -> {
this.updateColumn(c3, h3 = !h3);
this.resize();
});
Button hide4 = new Button(this.root, SWT.PUSH);
hide4.setText("Hide column 4");
hide4.addListener(SWT.Selection, E -> {
this.updateColumn(c4, h4 = !h4);
this.resize();
});
for(int i = 0; i < 20; i++)
{
TableItem ti = new TableItem(table, SWT.NONE);
ti.setText(new String[] {"c1:" + i, "c2:" + i, "c3" + i, "c4" + i});
}
return root;
}
protected void updateColumn(TableColumn c, boolean hide)
{
if(hide)
{
c.setResizable(false);
c.setWidth(0);
}
else
{
c.setResizable(true);
c.setWidth(300);
}
}
protected void resize()
{
this.root.getDisplay().asyncExec(() -> this.root.getShell().layout(null, SWT.ALL | SWT.CHANGED));
}
How do i make so that positions adapts to the new window position when i resize my window in SDL2 and with SDL_RenderSetLogicalSize?
I want to be able to hover a text and make it change color but whenever i resize the window its still in the same window cords. Is there a way to adapt the mouse?
void MainMenu::CheckHover()
{
for (std::list<MenuItem>::iterator it = menuItems.begin(); it != menuItems.end(); it++)
{
Text* text = (*it).text;
float Left = text->GetX();
float Right = text->GetX() + text->GetWidth();
float Top = text->GetY();
float Bottom = text->GetY() + text->GetHeight();
if (mouseX < Left ||
mouseX > Right ||
mouseY < Top ||
mouseY > Bottom)
{
//hover = false
text->SetTextColor(255, 255, 255);
}
else
{
//hover = true
text->SetTextColor(100, 100, 100);
}
}
}
I had a similar problem some time ago, and it was due to multiple updates of my mouse position in one SDL eventloop. I wanted to move a SDL_Texture around by dragging with the mouse but it failed after resizing, because somehow the mouse coordinates were messed up.
What I did was rearrange my code to have only one event handling the mouse position update. Also I'm not using any calls to SDL_SetWindowSize(). When the user resizes the window the renderer is resized appropriately due to SDL_RenderSetLogicalSize().
The relevant code parts look like this - some stuff is adapted to your case. I would also suggest to use a SDL_Rect to detect if the mouse is inside your text area, because the SDL_Rects will be resized internally if the the window/renderer changes size.
//Declarations
//...
SDL_Point mousePosRunning;
// Picture in picture texture I wanted to move
SDL_Rect pipRect;
// Init resizable sdl window
window = SDL_CreateWindow(
"Window",
SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex),
SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex),
defaultW, defaultH,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE );
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); // This one is optional
SDL_RenderSetLogicalSize(renderer, defaultW, defaultH);
// SDL main loop
while(SDL_PollEvent(&event) && running)
{
switch (event.type)
{
// Some event handling here
// ...
// Handle mouse motion event
case SDL_MOUSEMOTION:
// Update mouse pos
mousePosRunning.x = event.button.x;
mousePosRunning.y = event.button.y;
// Check if mouse is inside the pip region
if (SDL_EnclosePoints(&mousePosRunning, 1, &pipRect, NULL))
{
// Mouse is inside the pipRect
// do some stuff... i.e. change color
}
else
{
// Mouse left rectangle
}
break;
}
}
I use Dojo Toolkit 1.7.2 from http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js
I need to show scrollable (with help touch) content inside dialog. Also, if possible, I will need to have transition between views inside dialog like at mobile too.
What I do (simplified version of code):
var dialog = new Dialog();
var view = new ScrollableView({
selected: true
});
//add some content inside view. Content heigh is greater than height of dialog.
If I do this, the dialog tries to fit the whole height of the content.
Next attempt:
var dialog = new Dialog({
style: {
width: 600,
height: 400
}
});
or
dialog.resize({w: 600, h: 400});
Now dialog has fixed height, but inner ScrollableView instance won't scroll to bottom of its content.
When I dig into the source, I find that ScrollableView inherits from dojox/mobile/_ScrollableMixin which inherits from dojox/mobile/scrollable.
The resize() function of dojox/mobile/scrollable uses window height in order to calculate scrolling functionality.
Is there some way to have what I need without implementating my own version of ScrollableView?
Solution:
var dialogRect = domGeometry.getMarginBox(dialog.domNode);
var headerRect = domGeometry.getMarginBox(dialog.titleBar);
var containerNodePaddingTop = domStyle.get(dialog.containerNode, "paddingTop");
var containerNodePaddingBottom = domStyle.get(dialog.containerNode, "paddingBottom");
var viewHeight = dialogRect.h - headerRect.h - containerNodePaddingTop - containerNodePaddingBottom;
var view = new ScrollableView({
selected: true,
height: viewHeight.toString() + "px"
});
// or
// view.set("height", viewHeight.toString() + "px");
Fixed it this way:
var Name = 'yourdialogid';
dojo.query("#"+Name+" .dijitDialogPaneContent").forEach(function(node, index, arr){
dojo.style(node,"overflow","auto");
dojo.style(node,"height",(dojo.position(dijit.byId(Name).domNode).h-80)+"px");
});
I am building an air app in Flex 4. I am creating windows as I need them in a chromeless application.
Here is what I have in my main app creation complete
protected function creationCompleteHandler(event:FlexEvent):void
{
facade.sendNotification(AppFacade.APP_INIT, this);
var buttons:NavigatorWindow = new NavigatorWindow();
var workingSets:WorkingSets = new WorkingSets();
buttons.addElement( workingSets );
buttons.width = 115;
buttons.height =200;
buttons.maximizable = false;
buttons.resizable = false;
buttons.addEventListener(AIREvent.WINDOW_COMPLETE, onWindowComplete);
buttons.open();
}
private function onWindowComplete(event:AIREvent):void
{
event.currentTarget.x = 100;
event.currentTarget.y = 100;
}
for some reason the application adds the window in the middle of the screen and if I set the x and y of the Window it does not put it where I expect in the upper left of my screen. How do I position the window where I would like when it is opened?
thanks,
The spark.components.Window exists inside a NativeWindow you'll need to position the NativeWindow if you want to move it around on the screen. It is a bit confusing because you can position the Window inside the native window as well. You'll have to do the positioning after creation complete, otherwise you'll get null reference errors.
You could invoke the window like this if you created a component based on spark.components.Window:
var win:MyWindow = new MyWindow(); //MXML component
win.height = 150;
win.width = 300;
win.systemChrome = NativeWindowSystemChrome.NONE;
win.type = NativeWindowType.LIGHTWEIGHT;
win.showStatusBar = false;
win.transparent = true;
win.alwaysInFront = true;
win.open(true);
Then in that mxml component, you set an creationComplete event handler to do this:
var padding:int = 25;
this.nativeWindow.x = Screen.mainScreen.visibleBounds.right - this.width - padding;
this.nativeWindow.y = Screen.mainScreen.visibleBounds.top + padding;
This should put your new window in the top right hand corner with 25px of padding on the top and right.
I'm trying to create new GTK Notebook tabs that contain both a name (as a Label) and a close button (as a Button with an Image) with the following code:
Label headerLabel = new Label();
headerLabel.Text = "Header";
HBox headerBox = new HBox();
Button closeBtn = new Button();
Image closeImg = new Image(Stock.Close, IconSize.Menu);
closeBtn.Image = closeImg;
closeBtn.Relief = ReliefStyle.None;
headerBox.Add(headerLabel);
headerBox.Add(closeBtn);
headerBox.ShowAll();
MyNotebook.AppendPage(childWidget, headerBox);
This seems to work just fine; however, the button is about 1.5 - 2 times the size is needs to be, so there is a lot of extra space around the image inside the button. Having looked at remove inner border on gtk.Button I now see that the culprit is the "inner-border" style property of the GtkButton, but (being new to GTK) I can't seem to figure out how to override its value.
Is there some method of doing this that I'm missing? I don't have any reservations about not using a Button/Image combination, so any more obvious suggestions are welcome.
Note: I have seen the suggestion in the linked question to use an EventBox, but I was not able to add the Relief and mouseover effects to that Widget.
You are in luck. I just made the exact same thing yesterday, and can fortunately give you some code. The trick is to create a Custom Tab Widget.
public class MultiTab : Gtk.Box
{
public Gtk.Label Caption;
Gtk.Image img = new Gtk.Image(Platform.IMG + "tab_close.ico");
public Gtk.ToolButton Close;
public Gtk.Notebook _parent;
public MultiTab ( string name )
{
CreateUI(name);
}
public MultiTab(string name, Gtk.Notebook parent)
{
_parent = parent;
CreateUI(name);
CreateHandlers();
}
void CreateUI(string name)
{
Caption = new Gtk.Label(name);
Close = new Gtk.ToolButton(img,"");
PackStart( Caption );
PackStart( Close );
ShowAll();
Close.Hide();
}
void CreateHandlers()
{
Close.Clicked += delegate {
_parent.RemovePage(_parent.CurrentPage);
};
}
public bool Active;
}
Next all you have to do is use this widget(or a similar one created by you) in Gtk.Notebook like this:
MyNoteBook.AppendPage(new <YourPage>(), new MultiTab("<your caption>",this));
And You're done.
Here is a screenshot:
Add this:
RcStyle rcStyle = new RcStyle ();
rcStyle.Xthickness = 0;
rcStyle.Ythickness = 0;
closeBtn.ModifyStyle (rcStyle);
Add items to box using Gtk.Box.PackStart/PackEnd methods rather than generic Gtk.Container.Add method. PackStart/PackEnd will allow you control how child widgets will be allocated space:
headerBox.PackStart (headerLabel, true, true, 0);
headerBox.PackEnd (closeBtn, false, false, 0);