How to recalculate column widths on scroll down(not programmatic) to a previously hidden row of a Vaadin Grid when its HeightMode is CSS - vaadin

My application is similar to Vaadin Dashboard Demo (please click login after you visit this link). So all my mini dashboard items are wrapped around an abstract component that is of height 300px. One of those items is a Grid wrapped around this 300px height abstract component.
My customer hates it when he sees a large column and .v-grid-cell cuts his cell off:
text-overflow: ellipsis;
So in the #PostConstruct of my Vaadin Grid(and everywhere I mess with the container) i have
this.recalculateColumnWidths();
to alleviate my customer's concern. I tell him he can resize the column but he is not satisfied.
When my container size is small, most of the rows are visible and hence the column widths are perfect. When i have a lot of rows i have to scroll. The column widths are calculated based on the set of initially visible rows. When i scroll down, and if a newly visible row has a large column then the column gets cut off.
I can alleviate my problem by using HeightMode.ROW and make the parent Component a scrolling Panel like:
panel.setWidth("100%");
panel.setHeight("310px");
But I have a lot of action going on my Grid's FooterRow and so i don't want my user to have to scroll to the bottom to see the footers if row size is say 100. As a result my Grid has default HeightMode -> HeightMode.CSS. I like it. It always shows my HeaderRow and FooterRow and scrolls only the rows section of my Grid.
What have i tried:
Give each column humongous size or expand ratio. Customer rejected it.
I tried adding a listener for scroll event unsuccessfully. I used this similar question mentions. I could not get the scroll listener turned on.
ScrollingGrid.java:
public class ScrollingGrid extends Grid{
List<ScrollingGridScrollListener> listeners = new ArrayList<ScrollingGridScrollListener>();
private void fireSrollEvent() {
for (ScrollingGridScrollListener listener : listeners) {
listener.doGridScroll();
}
}
public void addScrollListener(ScrollingGridScrollListener listener) {
listeners.add(listener);
}
#Override
public void beforeClientResponse(boolean initial) {
super.beforeClientResponse(initial);
fireSrollEvent();
}
}`
ScrollingGridScrollListener.java:
public interface ScrollingGridScrollListener {
public void doGridScroll();
}
and in my Grid:
addScrollListener(this);
and
#Override
public void doGridScroll() {
Notification.show("You are scrolling!\nYou can add your own behavior here!");
this.recalculateColumnWidths();
}
I see the notification when page loads. Maybe i should not override beforeClientResponse method in Grid. But I don't know what method to override to achieve a scroll listener.
Help me figure out this scroll listener or if there is another way i can get recalculated column widths on scroll, please let me know.
Thanks for reading this very long question.
Version: 7.6.8

Related

How do I control the auto-scroll of an iOS Xamarin editor when the soft keyboard appears?

I'm encountering some bizarre behaviour in a Xamarin Forms iOS Editor.
I have needed the editor to expand horizontally with the width of the text, rather than wrapping.
To achive this, I placed the Editor inside a ScrollView:
<local:ScrollViewEx x:Name="svContent" HorizontalScrollBarVisibility="Default" Orientation="Both"
BackgroundColor="Transparent">
<local:EditorEx x:Name="edContent"
VerticalOptions="Fill" HorizontalOptions="Fill"
WrapLongLines="False"
BackgroundColor="Transparent" />
</local:ScrollViewEx>
In the editor renderer, everytime the text changes, I resize the editor's height and width by getting new dimensions from the following method:
Size GetSizeThatFits()
{
CGSize newSize = Control.SizeThatFits(new CGSize(nfloat.MaxValue, nfloat.MaxValue));
return new Size(newSize.Width, newSize.Height);
}
This all works fine.
But when the editor takes focus and the soft keyboard appears, the system will always horizontally scroll to the maximum x value of the line where the cursor sits. This can cause the cursor to be moved offscreen, and will obviously create confusion for users.
I have tried to control the scrolling by holding the x value in place and only allowing an autoscroll of Y as follows:
private void Editor_Focused(object sender, FocusEventArgs e)
{
double x = sv.ScrollX;
Device.BeginInvokeOnMainThread(() =>
{
sv.ScrollToAsync(x, sv.ScrollY, false);
});
}
This succeeds in holding my x value in place, but now Y for some reason is being automatically set to zero, ignoring the value of sv.ScrollY.
Any ideas?
UPDATE 01
I've just tested the app on an iPhone12 device and the problem is even worse.
With every keystroke the scroll will jump to a different part of the screen.
Is there anyway to completely decouple the keyboard and my Editor/ScrollView scrolling? It would be easier for me to write my scrolling behaviour completely by myself than to keep fighting with the built in behaviour which is not making sense.
UPDATE 02
I may be getting a little closer to my goal.
By subclassing my UITextView and enclosing UIScrollView and overriding their scroll related methods I've manage to kill off most of their unpredictable scroll behaviour:
public override void ScrollRectToVisible(CGRect rect, bool animated)
{
//do nothing
}
public override void SetContentOffset(CGPoint contentOffset, bool animated)
{
//do nothing
}
However some remains. The following scenario is causing problems:
TextChanged event
Reconstruct a UIStringAttributes based on new text, and assign it to Control.AttributedText (Scroll has stayed stable up to this point)
Control.TextStorage.BeginEditing();
Control.AttributedText = astr;
Control.TextStorage.EndEditing();
The next click on the editor to trigger cursor position / SelectionChange however causes an editor scroll setting ScrollY, and sometimes ScrollX to zero.
Why????
Step 3 is hard for me to manage because SelectionChange occurs with both a click on the editor and the entry of text. It also occurs before a TextChange so is hard to predict the cause of SelectionChange.
In addition, even if I bypass Step 2 and don't manually reset my AttributedText, the jump at Step 3 still occurs.
Any ideas?

set header and footer in BlackBerry in VerticalFieldManager

I searched how to set header and footer in BlackBerry and I found the functions setTitle() and setStatus().
My problem is I have created a class that extends VerticalFieldManager. In VerticalFieldManager, it is not showing me setStatus function as this is function of MainScreen class.
You're right. A VerticalFieldManager does not allow you to setStatus() directly.
It's important to understand the relationship between the classes in the BlackBerry UI framework.
First of all, there are Screen classes. Normally, a Screen will take up the entire device screen. You can have many different Screen classes in your app. Maybe one Screen for a splash image, one screen for a map view, one screen for settings, etc.
Inside your screens, you will often have Manager classes. A VerticalFieldManager is a kind of Manager that arranges its contents top-to-bottom, in the order that you add them. A Manager holds a group of related objects, but it does not have to span the full screen height, or width.
Inside your managers, you will usually have multiple Field objects. A Field is the individual item in the heirarchy. ButtonField, EditField, or BrowserField are all kinds of fields. They will usually be added to managers (containers). Those managers will then usually be added to screens.
So, in your case, I think what you should have is a screen class. In that screen class, you will set the header and footer by calling setTitle() and setStatus(). The content between the header and footer will all be contained in a VerticalFieldManager that you add to the screen. Something like this:
public class MyScreen extends MainScreen {
public MyScreen() {
super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
// set a header for this screen
setTitle("My Header / Title");
// screen contents go in the vertical field manager
// NOTE: you can replace VerticalFieldManager with your own class
// that extends Manager, or VerticalFieldManager, if you like
VerticalFieldManager vfm = new VerticalFieldManager();
vfm.add(new LabelField("One"));
vfm.add(new ButtonField("Two", ButtonField.CONSUME_CLICK));
vfm.add(new CheckboxField("Three", true));
add(vfm);
// use a bitmap as a footer
Bitmap footer = Bitmap.getBitmapResource("footer.png");
setStatus(new BitmapField(footer));
}
}

Spreadsheetgear column width changing event?

Is there any event in spreadsheetgear for worksheet column width changing? I want to perform some operation when user clicks on column separator and drags it to change its width in worksheet.
What precisely I want to do is to show a small tooltip indicating width/height of column/row, when user changes column width by column header, or row height from row header. Microsoft Excel has this behaviour, we can see a tooltip appears near column header when we change width/height for column/row.
Thanks
The WorkbookView class has an event called RangeChanged that triggers when a user changes the column width.
If you want to capture the new ColumnWidth after then change, the RangeChangedEventArgs parameter has that value.
public void workbookView1_RangeChanged(object sender, RangeChangedEventArgs e)
{
ToolTip ttip = new ToolTip();
ttip.Show(e.Range.ColumnWidth.ToString(), (SpreadsheetGear.Windows.Forms.WorkbookView)sender);
}
Be sure to add the following code to your designer.
this.workbookView1.RangeChanged += new SpreadsheetGear.Windows.Forms.RangeChangedEventHandler(this.workbookView1_RangeChanged);

Blackberry jumpy scroll

I am having trouble with vertical scrolling on a blackberry app.
it works just fine on touch screens, but when scrolling using a track pad, it jumps from being at the top position to being at the bottom position.
Anyone had a similar problem? any idea what i could try?
Here is a snippet from my code. i have a static background image and the fields scroll on top of it:
vertical_main = new VerticalFieldManager(USE_ALL_WIDTH |NO_VERTICAL_SCROLL |USE_ALL_HEIGHT);
vertical_AllTags=new VerticalFieldManager(USE_ALL_WIDTH | VERTICAL_SCROLL);
// i then add all the fields to vertical_AllTags
vertical_main.add(vertical_AllTags);
vertical_main.invalidate();
add(vertical_main);
thanks in advance for your help
EDIT:
The suggestion of giving each field focus was correct. the only other part that needs to be done is when you override the onFocus method for a field, you need to call the super() function so that all the other normal parts of the onFocus method are still called:
protected void onFocus(int direction) {
text_select=true;
invalidate();
super.onFocus(direction);
}
protected void onUnfocus() {
text_select=false;
invalidate();
super.onUnfocus();
}
Thank you so much.
This is common issue in non touch devises for beginners.
if you want to scroll field by field there is two ways
1) you need to give the focus to all fields then it will come field by
field focus down
another way is means you dont need to focus on each and every field
2)just add the NullField after your every field and give focus to all
NullFields then your trackball will bring your screen field by field
This happends beacuse in TrackWheel Scrolling it scrolls up to the next Focused field. I think you are not give any focus between the vertical_AllTags.
You can solved this by using NullField() class. Like...
add(new NullField(Field.FOCUSABLE))
when you add add(new NullField(Field.FOCUSABLE)); you will get the null focus which is not know by you. And you can navigate all the fields like Touch Screen.
You can solve that issue by adding two vertical field manager.. take a look at the code in this post

How to display Half screen?

I am working on a project where I need to display a ListField that takes the top half of the screen when the user clicks on a menu item. It should display on top of the earlier screen. How can I implement it?
Here are my ideas:
Use ListField directly with the above screen size to required screen.
Use PopupScreen with ListField
Use some screensplit functionality to display half of the screen
PopupScreen is best fit for your question. Can you try and post the code that didn't work?
Another option is to use managers to split the screen (higher manager and lower manager) and to hold another two managers: one that will be displayed on click and one that will be used as a pointer to the displayed Manager. Then, when ever the replace event is fired you should call the following function:
void updateManagers(boolean click)
{
if(click)
{
currentManager = afterClickManager;
}
else
{
currrentManager = beforeClickManager;
}
invalidate();
}
Where currentManager is an instance of Manager and afterClickManager & beforeClickManager are instances of some class which extends Manager (no need to be the same class).
Note that you should add currentManager to your screen layout before using the invalidate function.

Resources