Specific element on top oflist CellTable/ Pager - gwt

is it possible to have a specific element on top of the list?
backgoround:
I have an event app, where new events are constantly added. The events are orderd by date. If an event passes, it is still on top of the page. Now that some time passed, the first elements are all over, so the first paged doesn't display any necassery data anymore. To get to events which will happen, the user has to click on the pager button.
I want this events to be displayed on top, and if the user want's to see previous events, he has to click the back button of the pager.
What have I tried:
cellTable.setVisibleRange(overElements, (overElements + totalEementCount));
this mixes up the whole pager logic, and the user can't switch from pager to page anymore.
SingleSelectionModel<JSEvents> selectionModel = new SingleSelectionModel<JSEvents>();
...
selectionModel.setSelected(nextEvent, true);
this selects the right element, and moves the pager to it, but the other elements are still visible, so if I have a few "over" events and in the worst case, only have a single "comming" event in the table. Also it is the usability is bad, since the user has to look which event is next and doesn't have it on top of the page...

If you're using a ListDataProvider, you can add the new event to the front of the list. Everything depending on that dataprovider will be notified and should redraw.
If you're using a different kind of data provider, you may have to call CellTable.redraw yourself, but I think AbstractDataProvider takes care of that for you.
As a first investigative step, you might just try calling cellTable.redraw() after your new event has been logged to see if that gets you anywhere.

found a solution:
the celltable has a method setVisibleRange. This method is used in the examples when a pager involved:
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
end = end >= data.size() ? data.size() : end;
List<JSEvents> sub = data.subList(start, end);
updateRowData(start, sub);
the updateRowData tells the celltable, which data is displayed and on which position this data starts.
Now if we want to have a speciffic element on top of the page we can use the same function. This is how I end up using it:
int end = start + PAGESIZE;
end = (end >= data.size()) ? data.size() : end;
List<JSEvents> sub = data.subList(start, end);
dataProvider.updateRowData(start, sub);
cellTable.setVisibleRange(start, sub.size());

Related

How to know closing event of sub form in parent form

I have a main form with :
a table of data (list of pay)
a button calling a subform (assistant form to create easily a bound of pay for a complete year)
After closing the subform, I have to update the main form data (table view) only if the user click Generate (to avoid data update), ie only if the user generate new payroll.
Is there a way to know if the user cancel or not action in the subform?
Ok, so you NOT really talking about a form + sub form.
There are two ways to do this:
First, you can open the 2nd child form as acDialog (not modal - very big difference).
So, your main form code can do this:
Dim strF As String
strF = "frmChildForm"
DoCmd.OpenForm strF, , , , , acDialog
' CODE WILL HALT and wait for above form to be closed
' code here continues
' can even update data on this main form from that child form.
If CurrentProject.AllForms(strF).IsLoaded Then
' user hit ok - or your save button
Me.LastChildUpdate = Forms(strF)!LastUpdate
DoCmd.Close acForm, strF
Else
' code goes here - user hit cancel button, or X to close - we assume cancel
End If
Now in that other child form, you DO NOT CLOSE when your "done/save/ok" button runs. It simply sets the form's visible property to false
eg:
Me.Visible = False
So, now our calling code will WAIT until the user is done. If the form is closed, then we assume a user "canceled" that child form.
so, the user can hit X to close, OR the user might hit your close/cancel button. Your close/cancel button thus can close the form. eg this code:
docmd.Close acForm,me.name
So, now you know if the user canceled (closed) the form. Your "ok/save" button in that form ONLY sets the forms visible=False. That makes the calling code continue, and then you check if the form is open or not - and thus your code can take appropriate action.
However, you don't even have to use the "halt" code trick above.
What you can do in that child form you launch?
You can in the on-open event, or even on-load? You pick up the name of the calling form.
So, you define this in your code:
Option Compare Database
Option Explicit
Dim frmPrevious As Form
Private Sub Form_Load()
Set frmPrevious = Screen.ActiveForm
End Sub
So, now your save button on this form?
It can call/use/update ANYTHING from the main previous form caller.
So, your save button can now;
frmPrevious.Refresh
Or
frmPrevous!LastName = me.LastName
So, you can do "anything" by replacing "me" with frmPrevous, and any operation (such as your custom save button on that 2nd form) can update, call code, refresh, or do anything it wants to operation on the first main calling form.
And you can even call subs/functions in that main form.
So, you could have a public sub in the main form, and in the 2nd form, on the close event do this:
Call frmPrevous.MySubName ' tell + call code in main form.
docmd.close acForm,me.name
So the above outlines two approaches:
First idea:
You open 2nd form as "acdialog" and the code waits. You either then close the 2nd form (considered a cancel), or you save visible=false and the calling code CONTINUES.
Second idea:
You pick up the previous form in the on-load event. Now your save button can directly update values, controls etc. in "frmPrevious", and then once done, you close the 2nd form in that "ok button" routine.
So, quite much is that in that 2nd form, you can directly update controls and do things to the first calling form with the above 2nd idea.
Or, as noted, you can HALT the calling code that opens the form, wait for user response, and then use the visible=false trick to allow the calling code to continue. Once again, since the 2nd form is still open, you are free to get/grab/take values from that STILL open form, and then when done you thus as a last stop close that 2nd form. So in effect, your 2nd form does NOT close when the user is done - but only visible = false. As noted, this trick only works if you open/call the 2nd form as "acDialog". This is a great idea for say yes/no dialog prompts etc., since then you can upon user selection have the calling code continue, and examine the values in that 2nd form before closing it.
And the last but not least method:
In that 2nd form the code behind your "ok" button can simple update the first form
forms!MyFirstForm!LastName = me.LastName
docmd.close acForm,me.name
However, above has the form(s) name hard coded, and frmPrevious trick is thus somewhat better since then you don't hard code the calling forms name, and thus many forms can call + use that same 2nd form.

Excel Form VBA Combobox reset

This should be easy but I can't seem to find anything to solve. I have a Form in Excel using VBA. The Excel sheet has four columns populated with data and the Form displays those fields.
The user then selects a value in a combobox, uses a command button to submit the responses and the values from the combobox are written to the Excel sheet.
The user then uses a command button to advance one row down in the spreadsheet and load the four values from a new row. This all works great.
The issue I am trying to solve is that the combobox remains selected to the value in the prior selection. I'd like to reset the combobox so nothing is selected and the user has to make a selection again for the next row.
Below is the code I am using to load the combobox and to set a variable for what the user selected. Can't seem to get the combobox back to it's default state after the user has submitted the form.
Private Sub cbDesAccWanted_Change()
Select Case cbDesAccWanted.Text
Case "Yes"
desacc = "Yes"
Case "No"
desacc = "No"
End Select
cbDesAccWanted.Text = desacc
End Sub
Private Sub cbDesAccWanted_DropButtonClick()
cbDesAccWanted.List = Array("Yes", "No")
End Sub
There are two ways to reset the combobox. Take your pick:
1
cbDesAccWanted.Value = Null
2
cbDesAccWanted.ListIndex = -1
the line
cbDesAccWanted.Text = desacc
is totally unnecessary.
Using cbDesAccWanted_DropButtonClick is not the right place to populate the list of values. This list should be set up when the form is first shown to the user.
(unelss the values it shows chnages in which case change it when the row changes or something, not when the user clicks on it)
So when theuser clicks the down arrow to move to thenext record include the following line
Me.cbDesAccWanted.text = Me.cbDesAccWanted.List(1)
Note (1) access teh 2nd item in the list which is No.
So this reset it to the default value of No.
Ok.

MS Access POS (point of sale) application - Dynamically populate a form from a list

I need to create a small MS Access touchscreen POS (point of sale) application.
If someone has a rudimentary touchscreen MS Access template they can point me to, so that I can learn from it, that would help tremendously.
I have been able to find code for a touchscreen keyboard, which I will use.
The person using the interface needs to click on the name of a person as part of the POS process. The people change often, so I need to update the list often.
I am looking for a way to use VBA to create the onscreen buttons dynamically based on a list of people I update in a separate form.
The form will naturally be full-screen, and will never have more than 50 buttons on the screen representing the list of people. Only a few (less than 5) other controls will be present on this form, so the buttons representing the list of people needs to be constrained to an area on the form. The form must read the list of people, then create fixed sized, large square buttons automatically and be arranged alphabetically from left to right.
Thank you.
Something like this should work for you then. You'll need to make the max amount of buttons you will need on the form and space them and make an OnClick event for each like the one here for Command0. Then when the form is opened the array is initialized and all the buttons are captioned and made visible up to the amount of records in the table.
When each button is clicked it calls the HandleClick Sub to interact with the data as you need.
I made the recordset global so that it is only filled once and avoid weird data issues if the customers table is updated while this form is in use.
Dim Buttons(1 To 4) As Control
Dim rst As DAO.Recordset
Private Sub Command0_Click()
HandleClick (1) 'number that corresponds to this button in the array as
'initialized in the Form_Load sub, hard coded
End Sub
Private Sub Form_Load()
'initialize the buttons
Buttons(1) = Me.Command0
Buttons(2) = Me.Command1
Buttons(3) = Me.Command2
Buttons(4) = Me.Command3
Dim sql As String
sql = "SELECT * FROM tblCustomers"
Set rst = CurrentDb.OpenRecordset(sql)
FillButtons
End Sub
Sub FillButtons()
If (rst.EOF And rst.BOF) = False Then
rst.MoveFirst
Dim itr As Integer
Do
Buttons(itr).Caption = rst("CustomerName")
Buttons(itr).Visible = True
rst.MoveNext
Loop While rst.EOF = False
End If
End Sub
Sub HandleClick(CustomerNumber As Integer)
'Here is where you do what you intended with the button using
'customer number to know which record was clicked
End Sub
It's a messy approach but it should work.

Preserve the scroll position of a Page

I have a page with many elements (forms and tables)
When I want add a row in a table I scroll the page to the table, I press a button to add a row, edit the info in a popup and press OK.
Then I insert the new row in the model and refresh() the model.
At this point the page auto scroll at the top, but I don't want this behavior!
I want that the page stay in the same Y position!
I see that sap.m.page has scrollTo function https://openui5.hana.ondemand.com/docs/api/symbols/sap.m.Page.html#scrollTo
but I don't know how take the position before the refresh()
The Page does unfortunately not have an API to get the current scroll position, but the idea is a good one we consider.
As a workaround you could access some private method of the Page - but only if you accept the risk that it breaks with a future version of UI5:
page.getScrollDelegate().getScrollTop()
To make it safer you should verify both methods exist before calling them and also check the returned value for plausibility. Then you are pretty safe that in the worst case it will again scroll to the top in some future UI5 version.
you have to fill the iTime parameter in scrollTo function - e.g. srollTo(100, 1) - then it works
using 0 for iTime does not work

Pager starts to change pages back and forth when clicking page links fast

I have a Pager extended from AbstractPager in which every time on range or row count changed I recreate NavLinks contained in it so pager looks like this:
1 2 3 … N-1 N N+1 … M-2 M-1 M
My algorithm works fine but when I start clicking on links fast (like really furiously) by the time one RangeChange event is performing (CellTable to which my pager is attached shows spin trying to fetch data on given page) there's already another ones coming to the EventBus. It results in changing current page back and forth in an infinite loop.
I tried to make paging links enabled only when current page is competely fetched by using Scheduler.get().scheduleDeferred and .scheduleFinally but with no luck.
My temporary solution is to enable paging links after 500 ms by using Scheduler.get().scheduleFixedDelay(), but I want to know how to get the exact moment of data on the current page being fully fetched.
Thanks.
If you have the same problem you need to hang LoadingChangeEvent.Handler on your CellTable, check if data is fully loaded and inform pager about it so pager can activate it's NavLinks:
pager.setDisplay(cellTable);
cellTable.addLoadingStateChangeHandler(new LoadingStateChangeEvent.Handler() {
#Override
public void onLoadingStateChanged(LoadingStateChangeEvent event) {
if (event.getLoadingState() == LoadingStateChangeEvent.LoadingState.LOADED) {
pager.activateNavLinks();
};
}
});
There's no way to do it internally in your pager since setDisplay() accepts HasRows and addLoadingStateChangeHandler() is in AbstractHasData (AbstractHasData implements HasData, HasData implements HasRows).