FastReport4 - Child bands inheritance - fastreport

I have this situation with child bands in my fast report4:
ColumnHeader band (this one is displaying on every page always)
Child band, let's call it ChildOne, is a child of ColumnHeader. This one is visible only on first page.
Child band, let's call it ChildTwo, is a child of ChildOne. This one must be visible on pages other than page1.
But, the problem is, ChildTwo obviously inherits the visibility property of ChildOne and is not being displayed on subsequent pages... How do I overcome this?
Thank you!

Solution:
One possible approach is to attach child bands dynamically. You may try with these steps:
Remove the links between bands (column header band and first child band, first child band and second child band)
Add these links at run-time using column header band's OnBeforePrint event.
Event handler:
procedure ColumnHeader1OnBeforePrint(Sender: TfrxComponent);
begin
Child1.Visible := False;
Child2.Visible := False;
if (<Page#> = 1) then begin
Child1.Visible := True;
ColumnHeader1.Child := Child1;
end
else begin
Child2.Visible := True;
ColumnHeader1.Child := Child2;
end;
end;

Related

How can I use .lookUp() before the stage is shown (or use it once the stage is shown)

I want to use .lookup() so that I can create an event for when the content of a TextArea is clicked, but I get null when I use textArea.lookup(".content"). After searching why this is, I found out that it returns null if called before stage.show(). My next reaction was to somehow check for an event that is cast once the stage is shown, but that event is only accessible if you have access to the stage itself, which I do not in this case. What else can I do?
Don't register the handler at the content node. Let TextArea deal with the creation of the content node on its own, register a event handler at the TextArea directly and use the pickResult of the event to determine, if the click happened inside the node with style class content.
textArea.setOnMouseClicked(evt -> {
Node n = evt.getPickResult().getIntersectedNode();
while (n != textArea) {
if (n.getStyleClass().contains("content")) {
// do something with content node
System.out.println("content: " + n);
break;
}
n = n.getParent();
}
});
Generate a layout pass on the node:
node.applyCss();
node.layout();
as defined in the answer to:
Get the height of a node in JavaFX (generate a layout pass)
After that, your lookup functions on the node should work as expected.

Grid scrolling after render ZK

I'm trying to scroll down to the bottom of a grid, after the model was setted.
1) I set the model:
myGrid.setModel(new ListModelList<Object>(myList));
2) I override the row renderer
myGrid.setRowRenderer(new RowRenderer<Object>() {
#Override
public synchronized void render(Row row,final Object data, int index) throws Exception {
row.setStyle("commonCellPadding");
.
.
.
row.appendChild(htmlMessage);
}
});
3) Finally if the list used to set the model is too big (the grid in the .zul has fixed height) i want to show the last results (the more recents in this case).
I need to scroll down automatically after the render. How can i do this?
Things i had try
a) Calling a javascript function after the render, this doesn't work due to the fact that the gridEle.scrollHeight attribute returns the fixed height of the grid setted in the zul (or 0 if not) and not the grid's height after the model was setted.
myGrid.addEventListener(ZulEvents.ON_AFTER_RENDER, new EventListener<Event>() {
public void onEvent(Event event) throws Exception
{
Clients.evalJavaScript("var gridEle = document.getElementById('"+myGrid.getUuid()+"-body"+"'); gridEle.scrollTop = gridEle.scrollHeight;alert(gridEle.scrollHeight);");
}
});
Why don't you sort the myList descending at first to make the last row become the first one instead to control the scroll bar?
In my opinion, it would be more easy and matching the users experience.
Just call Clients.scrollIntoView(rows.getLastChild()); after you have set the model and row renderer (provided rows is Rows component id and is already auto wired into your controller). See the live demo on zkfiddle here and source
UPDATE: Clients.scrollIntoView(Component) wouldn't work if you are using Render-On-Demand feature because naturally if the row that you want to scroll to wouldn't have been loaded on initial page load.

Xtrareports - report header problems

i have a report in .repx format. with a group header , detail and group footer.
The problem is when no more space for group footer on first page , the group footer is printed on next page , but on this page is printed the group header too , even if there's no more records in detail section . How can i do that if no more records in detail section the group header to be invisible on next page.
Thank you !
Refer this How do I hide the GroupFooterBand when the grouping field is empty or null?
There are two approaches to achieve this, but i suggest you to follow as below:
If you can find out which detail bands will be hidden in the
GroupHeaderBand.BeforePrint and GroupFooterBand.BeforePrint event
handlers, then you can hide corresponding group header and footer.
References:
Hide GroupHeader & GroupFooter
[source from the report.]
How to shrink groupHeader or to hide a xrtable in the groupHeader - don't work
suppress group footer if group header is suppressed
How to hide GroupFooterBand on the last page
GroupFooter BeforePrint with Hierarchical data structure
The solution I came up with for nearly an identical problem was to keep track of a counter that resets on each page.
First, wire up BeforePrint on the TopMargin band, which prints on every page:
private int detailsPrintedThisPage = 0;
private void TopMargin_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) {
detailsPrintedThisPage = 0;
}
Next, whenever a detail prints, keep track of that:
private void Details_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) {
detailsPrintedThisPage++;
}
Finally, on the group footer, if no details have printed this page, then suppress the footer:
private void GroupFooter1_BeforePrint(object sender, System.Drawing.Printing.PrintEventArgs e) {
e.Cancel = (detailsPrintedThisPage == 0);
}
The problem I was solving was initially the same as yours, except that my group footer was nothing but a blank label meant to provide padding between groups. The blank spacing was causing an entire page to print (with a group header) on the last page if the details lined up just right to be wrong, which is exactly the case you describe.
In my case, however, I simplified the problem by removing the footer altogether and added extra space before the group header that I suppressed if it was the first group header printed on a given page. However the code above is adapted from my solution to where it should work in the more general case you describe where you want to hide the group footer specifically if there are no details on the page. Sharing 7 years late in case it helps someone else who lands here...

Capturing mouseEevents on a container, bypassing its children

I am building an RIA application using Flex 4.6 that contains a main borderContainer (page) that can contain some other borderContainers (graphic or text elements).
I added an event listener on the page to listen to click events:
page.addEventListener(MouseEvent.CLICK, clickHandler, true);
clickHandler looks like this:
private function clickHandler(event:MouseEvent):void
{
// Remove event listeners
page.removeEventListener(MouseEvent.CLICK, clickHandler, true);
// Get click position
objX = event.localX;
objY = event.localY;
}
My problem is that although the event's currentTarget is always the page (normal), the target can either be the page or one of its children, and then localX doesn't give me the position on the page but on the child.
Is there a way to make sure the page is always the target of the event? Something like stopping the capturing phase on the page so it doesn't go deeper?
Thanks in advance for your help
Darrel
I think you may be asking the wrong question. As I understand it, you want the x/y position relative to 'page'. You can use the DisplayObject#globalToLocal() function to find this.
Just take the the global coordinates and convert them to local coordinates relative to 'page':
var coordinates:Point = new Point(event.stageX, event.stageY);
coordinates = page.globalToLocal(coordinates);
objX = coordinates.x;
objY = coordinates.y;

Flex - FlexPrintJob how to print a group of fields and a PrintDataGrid properly?

I am trying to print a multiple-page FlexPrintJob, that includes on the first page, several labels, then a PrintDataGrid. It all prints, except that the PrintDataGrid only prints using half the page on all the pages.
I know it has to do with the labels that I am printing on page 1, because taking them off or hiding them fixes the issue and the grid prints full page all pages.
I have tried various containers around the grid and labels, including VBox, VGroup, Group, and specifying different combinations of height="100%" for some of the containers.
Is it simply not possible to print a half page of variables / labels on page 1, then start the data grid on the same page (half page worth), but then have it go to full page on the following pages?
Here is my print job code:
var printJob:FlexPrintJob = new FlexPrintJob();
if (printJob.start()) {
var thePrintView:printViewEventUser = new printViewEventUser(); // Create a FormPrintView control as a child of the application.
addElement(thePrintView);
thePrintView.width=printJob.pageWidth;
thePrintView.height=printJob.pageHeight;
thePrintView.parentEncounter=parentEncounter; //pass in my object for the labels to print
thePrintView._currentRec=_currentRec; //pass in my object for the labels to print
thePrintView.myDataGrid.dataProvider = bedSearchEditList._recs;
thePrintView.showPage("single"); // Create a single-page image.
if(!thePrintView.myDataGrid.validNextPage) // If the print image's DataGrid can hold all the data provider's rows, add the page to the print job.
{
printJob.addObject(thePrintView,FlexPrintJobScaleType.NONE);
}
else // Otherwise, the job requires multiple pages.
{
thePrintView.showPage("first"); // Create the first page and add it to the print job.
printJob.addObject(thePrintView);
thePrintView.pageNumber++;
while(true) //queue pages
{
thePrintView.myDataGrid.nextPage(); // Move the next page of data to the top of the PrintDataGrid.
thePrintView.showPage("last"); // Try creating a last page.
if(!thePrintView.myDataGrid.validNextPage) // If the page holds the remaining data, or if the last page was completely filled by the last grid data, queue it for printing. Test if there is data for another PrintDataGrid page.
{
printJob.addObject(thePrintView,FlexPrintJobScaleType.MATCH_WIDTH); // This is the last page; queue it and exit the print loop.
break;
}
else // This is not the last page. Queue a middle page.
{
thePrintView.showPage("middle");
printJob.addObject(thePrintView,FlexPrintJobScaleType.MATCH_WIDTH);
thePrintView.pageNumber++;
}
}
}
removeElement(thePrintView);
}
printJob.send(); // Send the job to the printer.
My print view object is basically just an around my labels, then a PrintDataGrid.
If I remember correctly I fixed a similar situation in the past specifying a minHeight property to my mx:PrintDataGrid like this..
<mx:PrintDataGrid id="printViewDataGrid" width="100%" minHeight="500">
...
</mx:PrintDataGrid>
Good luck!

Resources