Can't apply absolute css positioning to my own composite button - css

Here is a strange problem I am having, althougt I have a work around I would still like to understand why it is happening.
Here is my Composite class
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.*;
public class ExpandingOvalButton extends Composite implements HasClickHandlers
{
private PushButton button;
private Label label = new Label();
private AbsolutePanel panel = new AbsolutePanel();
public ExpandingOvalButton(String text)
{
int width = 40;
initWidget( panel );
Image image = new Image( "icons/ovalBlueButton.png");
label.setText(text);
width = width + (text.length() * 8);
String widthStr = width + "px";
image.setWidth(widthStr);
image.setHeight("50px");
button = new PushButton( image );
button.setWidth(widthStr);
button.setHeight("50px");
panel.setSize(widthStr, "50px");
panel.add(button, 0, 0);
panel.add(label, 18, 14);
}
...
It works perfectly for me when I add it to a flex table along with other widget and then I can apply css styles to the flextable and position it fine. Problem is if I want to apply css positioning to a ExpandingOvalButton instance which does not sit inside of an other panel it does not work properly.
private ExpandingOvalButton startBtn = new ExpandingOvalButton("Start");
startBtn .getElement().setId("myId");
#myId
{
position: absolute;
left: 30%;
top: 120px;
}
This will NOT position itself 30% from the left side.
However if I add startBtn to a Panel and then apply the same CSS style to the Panel it WILL position itself 30% from the left.
panel.add(startBtn);
panel.getElement().setId("myId");
Anyone come across this before or know what might be causing it?

If you look at the source code for AbsolutePanel, you will find this in the constructor:
DOM.setStyleAttribute(getElement(), "position", "relative");
This has priority over the styles declared in your css. You can force it to use absolute positioning by doing something similar:
DOM.setStyleAttribute(startBtn.getElement(), "position", "absolute");

Related

Override JavaFX CSS style in code

Is it possible to override a JavaFX CSS definition in code?
For example, in my CSS file I defined a button's height as follows:
.button {
-fx-pref-height: 30px;
}
When I try to override this height for some button in code...
Button button = new Button();
button.setPrefSize(100, 50); // width, height
...the button still has a height of 30 pixels.
There are two solutions:
Make sure that button.setPrefSize(100, 50); // width, height is called after the Button became visible.
Use Bindings to force its size (CSS does not overwrite bound values), for example: button.prefHeightProperty().bind(new SimpleDoubleProperty(60));

How to achieve an smooth height transition when adding new elements to a Panel in GWT?

I have a FocusPanel that when gets clicked adds new Elements/Widgets to itself making its height increase. Note, that there is no explicit change of height in the css of the FocusPanel, the height just increases as the result of adding new elements inside the panel
I would like that increase in height to occur through a smooth transition but I am not sure how to achieve it.
I tried applying css transition: height 2s; to the FocusPanel and also to all the other Elements/Widgets that I add to it. But it does not seem to work, there is no transition at all. I assume it is because the height does not increase as a result of me changing the css property but rather by just adding more elements to a container.
What is the right way to achieve a smooth transition of height when adding new elements programatically to a Panel? Thanks!
PS. A good example of what I would like to achieve is the way twitter handles the transition of the panel height when one clicks on a twit.
CSS animations only work if you set the height to fixed values.
A way is to create your own implementation of panel, and override the add method, so as it takes care of computing height and setting it before and after animation time.
As #fascynacja points in its comment, I would go with gwtquery to do that, because of different reasons, but main one is that it is a lightweight library developed in gwt which allows you doing a lot of things with few code lines.
Here you have an example of a panel doing what you want using gquery animations.
import static com.google.gwt.query.client.GQuery.*;
[...]
// Create your own implementation of a panel
public static class MyFlowPanel extends FlowPanel {
// The GQuery object for this panel
GQuery $this = $(this);
// Override the add method so as each time it is called, we run an animation
// You can do the same with the remove method.
#Override
public void add(Widget w) {
// Compute the actual height
int hInitial = $this.height();
// Set height to auto before adding the new child.
$this.height("auto");
// Add the new widget to panel
super.add(w);
// Compute the new height
int hFinal = $this.height();
// Use Gquery to .animate the panel from the old to the new height
// You could replace this with css3 transitions
$this.height(hInitial)
.stop(true)
.animate("height: " + hFinal, 2000);
};
};
public void onModuleLoad() {
// Create your panel, and use it as usual in GWT
final FlowPanel myFlowPanel = new MyFlowPanel();
RootPanel.get().add(myFlowPanel);
// Set some css properties to your panel. You could set these in your style-sheet.
$(myFlowPanel).css($$("border: 1px solid grey; border-radius: 8px; background: #F5FFFA; width: 500px; padding: 8px"));
// Add 10 labels to the panel in periodes of 1000 ms
Scheduler.get().scheduleFixedPeriod(new RepeatingCommand() {
int c = 10;
public boolean execute() {
if (c-- > 0) {
myFlowPanel.add(new Label(c + " Lorem ipsum dolor sit amet, consectetur adipiscing elit."));
return true;
}
return false;
}
}, 1000);
}

GWT: Help trying to format a composite widget. Tried CSS stuff and it has no effect

Consider the following widget:
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.FlexTable;
public class SelectorPanel extends Composite
{
private final FlexTable flexTable = new FlexTable();
private final Label lbltitle = new Label("##Title");
private final ListBox listBox = new ListBox();
private final Label lblsearchtext = new Label( "##SearchText" );
private final TextBox tbSearch = new TextBox();
public SelectorPanel()
{
listBox.setVisibleItemCount( 10 );
flexTable.setStyleName("SearchPanel");
flexTable.setBorderWidth(0);
initWidget( flexTable );
flexTable.setSize("200px", "0px");
lbltitle.setWordWrap( false );
flexTable.setWidget( 0, 0, lbltitle );
flexTable.setWidget( 1, 0, listBox );
listBox.setWidth("100%");
flexTable.setWidget( 2, 0, lblsearchtext );
tbSearch.setMaxLength( 32 );
flexTable.setWidget( 3, 0, tbSearch );
flexTable.getCellFormatter().setHorizontalAlignment( 0, 0, HasHorizontalAlignment.ALIGN_LEFT );
flexTable.getCellFormatter().setVerticalAlignment( 2, 0, HasVerticalAlignment.ALIGN_MIDDLE );
flexTable.getCellFormatter().setVerticalAlignment( 1, 0, HasVerticalAlignment.ALIGN_MIDDLE );
flexTable.getCellFormatter().setVerticalAlignment( 3, 0, HasVerticalAlignment.ALIGN_MIDDLE );
flexTable.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_BOTTOM);
flexTable.getCellFormatter().setHorizontalAlignment(3, 0, HasHorizontalAlignment.ALIGN_CENTER);
}
}
I have tried messing with CSS spacing and padding (and I have no idea what the difference is) and it has no effect. I can even change colors in the CSS tool and that too has no effect.
Anyway, here are the problems with widget:
The title text "##Title" is cut off by the list box below it. I would like some spacing or padding below it so that doesn't happen.
The ##SearchText label is too close to the listbox above it and also overlapped by the text box below it.
Finally the whole thing appears at the extreme left on my browser and I would like a little spacing between it and the edge of the screen.
I can 'kind of' format this by adjusting cell sizes and what not. I can't get it right, only better. I am also thinking this must be the wrong way to go about it.
When I look at the stockwatcher application they use CSS to do things like this, but I can't get anything to happen. The following is my CSS file and the two items are just experimental and have no effect on anything.
Boxed {
margin-top: auto;
border: thin solid;
background-color: Silver;
}
#test {
margin-top: 20px;
margin-bottom: 20px;
padding-top: 20px;
padding-bottom: 20px;
}
Is there anyone who can explain this to me? I just do not understand why CSS has no effect or how to resolve the above problems. I can apply the above CSS to the cells or to the labels or other UI objects and nothing happens.
first of all i can't see your overlapping issues. See the picture. This looks good to me:
To the CSS-questions: You need to reference the Class-Name or the ID of you component. A class is referenced by ".className", an id by "#id".
If you want to move your widget to the left by 100 pixels you can use this CSS:
.SearchPanel{ margin-left:100px; }
Or you can even center it with:
.SearchPanel{ margin:auto; }
You applied the css-class "SearchPanel" in your code with:
flexTable.setStyleName("SearchPanel");
This way you can apply classes to every component.
If you wan't more spacing on the top and the bottom of your label (##Title and ##SearchText) you could add some margin as well:
.gwt-Label {
margin-top: 10px;
margin-bottom: 10px;
}

Scrolling through list element causes text elements to scroll as well

I'm using a list element with variableRowHeight and word-wrap set to true like in the example below:
http://blog.flexexamples.com/2007/10/27/creating-multi-line-list-rows-with-variable-row-heights/
When I scroll through the list with a mouse scrollwheel the text in the listItems also scroll. I know that this is to do with the height of the textField... but I am unsure how to best resolve this issue. Any thoughts are appreciated!
The issue that I am experiencing also occurs in the example above.
OK, solved it after a bit of work. Thought I would put it here for others:
This can be simply solved by extending the List element, and the ListItemRenderer and modifying a couple of lines:
First up, extend the List element:
package au.com.keeghan.controls {
import mx.controls.List;
import mx.core.ClassFactory;
public class ExtendedList extends List{
public function ExtendedList(){
super();
itemRenderer = new ClassFactory(ExtendedListItemRenderer);
}
}
}
Now we want to extend the newly created item renderer (ExtendedListItemRenderer). Because there isn't actually that much code required, we can just put it in the same .as file. We do this by declaring it as a internal class, and locating it outside of the package above... just below the closing bracket:
import mx.controls.listClasses.ListItemRenderer;
internal class AsOneListItemRenderer extends ListItemRenderer{
override protected function measure():void{
super.measure();
var w:Number = 0;
if (icon)
w = icon.measuredWidth;
// Guarantee that label width isn't zero
// because it messes up ability to measure.
if (label.width < 4 || label.height < 4)
{
label.width = 4;
label.height = 16;
}
if (isNaN(explicitWidth))
{
w += label.getExplicitOrMeasuredWidth();
measuredWidth = w;
measuredHeight = label.getExplicitOrMeasuredHeight();
}
else
{
measuredWidth = explicitWidth;
label.setActualSize(Math.max(explicitWidth - w, 4), label.measuredHeight + 3);
label.validateNow();
label.height = label.textHeight + 5;
measuredHeight = label.getExplicitOrMeasuredHeight() + 3;
if (icon && icon.measuredHeight > measuredHeight){
measuredHeight = icon.measuredHeight;
}
}
}
}
Now, the majority of the above code is actually just copied from the ListItemRenderer, the magic occurs down the bottom... specifically these lines:
label.setActualSize(Math.max(explicitWidth - w, 4), label.measuredHeight + 3);
label.validateNow();
label.height = label.textHeight + 5;
measuredHeight = label.getExplicitOrMeasuredHeight() + 3;
All I do here is add some height to both the label, and the overall measuredHeight which in the end is the thing that is causing this issue.
The only downside to this solution is that you will get a larger amount of padding below the listItem element, however you can still make this look good by playing around with the verticalAlign and padding css properties.

Creating a Flex Panel header with a gradient

I need a white box (I'm using a Panel because I'm so close, but it could be anything) with all four corners rounded, and the top portion of the box needs to have a gradient that starts out one color (let's say Grey) and ends up as the background color (white). The gradient does not go down the entire box.
The top two corners must remain rounded, so the gradient must fill those rounded regions too.
What I have so far is an mx:Panel with the following styles:
Panel {
borderColor: #ffffff;
borderAlpha: 1;
borderThickness: 13;
borderThicknessLeft: 0;
borderThicknessTop: 0;
borderThicknessBottom: 11;
borderThicknessRight: 0;
roundedBottomCorners: true;
cornerRadius: 16;
headerHeight: 50;
backgroundAlpha: 1;
highlightAlphas: 0.29, 0;
headerColors: #999999, #ffffff;
backgroundColor: #ffffff;
dropShadowEnabled: false;
}
As you can see, there is one tiny single-pixel line that cuts across the header. If I can just get rid of that single-pixel line, that would be perfect! I have tried changing the borderStyle property to "solid" and still cannot get the right combination of styles to get rid of that line.
I have also tried using another container with a background image for the gradient, but the rounded corners become an issue.
Any help would be greatly appreciated!
The culprit for the line under the title bar is actually the default titleBackgroundSkin associated with the Panel component (mx.skins.halo.TitleBackground). If you look at the source of the updateDisplayList method you see a section where it draws the background that includes the following lines:
g.lineStyle(0, colorDark, borderAlpha);
g.moveTo(0, h);
g.lineTo(w, h);
g.lineStyle(0, 0, 0);
If you create your own implementation that does everything the same with the exception of these lines, you should get what you need. At least I did in my limited test case with a gradient header.
The following css gets rid of the line, but prevents you from using a gradient header.
.richTextEditor
{
titleBackgroundSkin: ClassReference("mx.skins.ProgrammaticSkin"); /** Gets rid of the line that was there **/
}
I didn't find a solution to the specific Panel issue above, but I did find an overall solution that works for any container: set a background image using bitmapFill and round the corners.
This is what worked for me (using a programmatic skin):
[styles.css]
HBox {
borderSkin: ClassReference("assets.programmatic.GradientHeaderSkin");
}
[GradientHeaderSkin.as]
package assets.programmatic
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import mx.skins.ProgrammaticSkin;
public class GradientHeaderSkin extends ProgrammaticSkin
{
[Embed(source="../imgs/panelHeaderGradient.png")]
private var _backgroundImageClass:Class;
private var _backgroundBitmapData:BitmapData;
private var _backgroundImage:Bitmap;
private var _backgroundColor:uint;
public function GradientHeaderSkin()
{
super();
_backgroundImage = new _backgroundImageClass();
_backgroundBitmapData = new BitmapData(_backgroundImage.width, _backgroundImage.height);
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
_backgroundBitmapData.draw(_backgroundImage);
graphics.clear();
graphics.beginBitmapFill(_backgroundBitmapData, null, false, false);
// specify corner radius here
this.graphics.drawRoundRectComplex(0, 0, this.width, this.height, 20, 20, 20, 20);
}
}
}
Here is also an example which loads an external image:
http://books.google.com/books?id=7fbhB_GlQEAC&pg=PA106&lpg=PA106&dq=flex+filling+rounded+corners+with+graphic&source=bl&ots=HU_jainH4F&sig=F793bjL0a4nU5wx5wq608h_ZPr0&hl=en&ei=GQd3Spi-OYiYMcLDyLEM&sa=X&oi=book_result&ct=result&resnum=1#v=onepage&q=&f=false

Resources