Infragistics grid scrolling issue - infragistics

I have this code, which works fine if a cell in the IgGrid control is being edited:
var verticalContainer = $("#BookLabor_scrollContainer");
var topPos = verticalContainer.scrollTop();
$("#BookLabor").igGrid("option", "dataSource", blankLaborDS);
$('#BookLabor').igGrid('dataBind');
verticalContainer.scrollTop(topPos);
However, when I use an IgDialog that I have pop open on a grid cell with a button click event, this is not scrolling back to the row being edited:
var verticalContainer = $("#BookLabor_scrollContainer");
var topPos = verticalContainer.scrollTop();
$("#BookLabor").igGrid("option", "dataSource", blankLaborDS);
$('#BookLabor').igGrid('dataBind');
verticalContainer.scrollTop(topPos);
There is a virtual scroll method for the IgGrid, but the online documentation does not explain in detail how to use it.
Any tricks, tips, hints from all you Infragistics experts out there?

The scroll related API is very basic and what you are using is pretty much comparable:
.igGrid("scrollContainer") is merely a shorthand so you don't have to use #BookLabor_scrollContainer (it's an internal id)
.igGrid("virtualScrollTo", scrollContainerTop); is just like scroll top when you are using virtual scrolling, which you might be (can't tell without more code) so you might want to try that out.
HOWEVER, is there a reason to call dataBind after cell edit? ( I'm having a hard time finding a scenario for that). It is not intended by any means and it creates a lot of overhead with bigger data. If you need to update cell values you should be using the Updating API that does not require re-bind and will not require scroll after as well..see:
http://help.infragistics.com/jQuery/2012.2/ui.iggridupdating#methods
As for the dialog, the Updating again provides a row template that internally uses the dialog and I highly recommend that if row editing is acceptable. Sample:
http://www.infragistics.com/products/jquery/sample/grid/row-edit-template

Related

Reordering MFC control IDs automatically

I've got a pretty old MFC application that's been touched by many people over the years (most of them probably not even CS guys) and it follows, what I like to call the "anarchy design pattern."
Anyway, one of the dialogs has a series of 56 vertical sliders and check boxes. However, there are additional sliders and checkboxes on the dialog as shown below.
Now, the problem is that the additional sliders and checkboxes take on IDs that are in sequence with the slider/checkbox series of the dialog. My task is to add more sliders and checkboxes to the series (in the blank space in the Slider Control group box) Unfortunately, since IDC_SLIDER57 through IDC_SLIDER61 are already in the dialog (same goes for the checkboxes), existing code, such as the snippet below will break:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
Is there a better way to modify the resource file without doing it manually? I've seen a third party tool called ResOrg that looks like it'll help do what I want, but the software is a bit pricey, especially since I'll only use it once. I guess I can give the demo a try, but the limitations might restrict me.
FYI, I'm using Visual C++ 6.0 (yes...I know, don't laugh, it's being forced upon me).
Instead of writing:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
you could write:
pVSlider = (CSliderCtrl *)GetDlgItem(GetSliderID(i));
where GetSlider is a function that returns the id of slider number i.
GetSlider function
int GetSliderID(int nslider)
{
static int sliderids[] = {IDC_SLIDER1, IDC_SLIDER2, IDC_SLIDER3, .... IDC_SLIDERn};
ASSERT(nslider < _countof(sliderids));
return sliderids[nslider];
}
With this method the IDC_SLIDERn symbols dont need to have sequential values.

QtWebView - How to enable scrolling of page and scrolling of elements in a page (e.g. Google Maps)

I've run into a bit of an issue related to a whitelist Web Browser my company has been developing / maintaining for one of our product lines. The browser runs on top of Qt 4.8.6, using qtwebkit (Migration to 5.X would be ideal, but the embedded Linux OS we're using is too old to support the newer versions based on our testing, and upgrading to a newer OS is too costly to us / our customers). The primary interface to the browser is a 6x8 touchscreen, mounted inside an aircraft cockpit.
For sites that have things like scrollable/embedded maps (ex. Google Maps), the users of the browser want the ability to drag the entire page when they are selecting something outside of the map, and drag just the map (without the entire page scrolling) when the map is selected (Ala most of the popular mobile browsers).
Thus far, I am able to do one or the other, but not both:
When I hook mouse handlers into a QWebView or QGraphicsWebView, I can turn the cursor into a hand and very easily support dragging of the entire web page. However, that inhibits the page's ability to handle the mouse events for when a user is pulling over a map (i.e. When a user drags over a map, it drags the entire page without moving the map).
When I don't add in the hooks to handle mouse events, things like maps are scrollable by grapping/dragging them, but of course the user loses the ability to drag the entire page.
Right now, the browser uses the later, with scroll bars disabled and a directional-arrow overlay to allow the user to scroll the entire page (as the display size is limited, and scrollbars take up too much space when they are sized large enough for the user to interact with them)...but this is not ideal.
My Question: Is there any easy way to make it so that the page, and elements in a page, can be scrolled seamlessly?
Thanks!
Rob
Seems to me like you need to check if you are over such a map and ignore(pass along) the event in that case. I think you should be able to do something like this:
bool GraphicsWebView::isOverMap(QPoint pos) {
QWebPage* webPage = this->page();
if (webPage) {
QWebFrame* webFrame = webPage->frameAt(pos);
if (webFrame) {
QString selectorQuery = "#map-canvas"; // Based on https://developers.google.com/maps/tutorials/fundamentals/adding-a-google-map
QList<QWebElement> list = webFrame->findAllElements(selectorQuery).toList(); // Find all the maps!
foreach(QWebElement element, list) {
if (element.geometry().contains(pos)) {
return true; // Cursor is over a map
}
}
}
}
return false; // No match
}
Obviously this is a pretty specific function but there is probably a way to come up with a better selector query that will apply to all those kinds of QWebElement.
Assuming you hook mouse events by subclassing QGraphicsWebView and reimplementing void mouseMoveEvent(QGraphicsSceneMouseEvent * event), I suggest you do something like:
void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
if (isOverMap(mapFromScene(event->scenePos()).toPoint())) { // We got a map!
event.ignore(); // Clear the accept flag
return; // Return, we're done here
}
handleMoveView(); // Not over any maps, let's scroll the page
}
This part of the doc explains how events are handled with regard to the topmost item. I especially recommend you read the third paragraph.
Hope that helps!
EDIT: Did a bit more research and it looks like something like that could be more generic:
graphicsView.focusItem()->flags().testFlag(QGraphicsItem::ItemIsMovable);
It's at the very least worth investigating as a replacement to isOverMap()
EDIT: Gotcha, here is something you can try then.
Start by subclassing QGraphicsSceneMouseEvent and add a signal called void destroyedWithoutAccept() that's emitted in the destructor if the event has not been accepted.
Then modify mouseMoveEvent to look like this:
void GraphicsWebView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
MyEvent myEvent = new MyEvent(event); // Copy event
event.accept(); // accept original event
connect(myEvent, SIGNAL(destroyedWithoutAccept),
this, SLOT(handleMoveView)); // Callback if unused
QGraphicsWebView::mouseMoveEvent(myEvent); // Pass it to Base class
}
If that works, it might introduce a bit of delay if deleteLater is used to destroy it. But in that case reimplement it as well.

Using images in QListWidget, is this possible?

I am using QT to create a chat messenger client. To display the list of online users, I'm using a QListWidget, as created like this:
listWidget = new QListWidget(horizontalLayoutWidget);
listWidget->setObjectName("userList");
QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Expanding);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(listWidget->sizePolicy().hasHeightForWidth());
listWidget->setSizePolicy(sizePolicy1);
listWidget->setMinimumSize(QSize(30, 0));
listWidget->setMaximumSize(QSize(150, 16777215));
listWidget->setBaseSize(QSize(100, 0));
listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
Users are shown by constantly refreshing the list, like this: (Note: There are different channels, with different userlists, so refreshing it is the most efficient thing to do, as far as I know.)
void FMessenger::refreshUserlist()
{
if (currentPanel == 0)
return;
listWidget = this->findChild<QListWidget *>(QString("userList"));
listWidget->clear();
QList<FCharacter*> charList = currentPanel->charList();
QListWidgetItem* charitem = 0;
FCharacter* character;
foreach(character, charList)
{
charitem = new QListWidgetItem(character->name());
// charitem->setIcon(QIcon(":/Images/status.png"));
listWidget->addItem(charitem);
}
}
This has always worked perfectly. The line that I commented out is the one I have problems with: my current goal is to be able to display a user's online status with an image, which represents whether they are busy, away, available, etc. Using setIcon() does absolutely nothing though, apparently; the items still show up as they used to, without icons.
I'm aware that this is probably not the way this function needs to be used, but I have found little documentation about it online, and absolutely no useful examples of implementations. My question is, can anybody help me with fixing this problem?
This is how you may conduct your debugging:
Try the constructor that has both icon and text as arguments.
Try to use that icon in another context to ensure it is displayable (construct a QIcon with same argument and use it elsewhere, e.g. QLabel!).
Use icon() from the QListWidgetItem to receive back the icon and then look at that QIcon.
Create a new QListWidget, change nothing, and ordinarily add some stock items in your MainWidget's constructor. See if the icons show up there.

MFC: Displaying a tabulated display of text items

This should be simple it seems but I can't quite get it to work. I want a control (I guess CListBox or CListCtrl) which displays text strings in a nice tabulated way.
As items are added, they should be added along a row until that row is full, and then start a new row. Like typing in your wordprocessor - when the line is full, items start being added to the next line, and the control can scroll vertically.
What I get when trying with a list-mode CListCtrl is a single row which just keeps growing, with a horizontal scroll bar. I can't see a way to change that, there must be one?
You probably need a list control wth LVS_REPORT. If you expect the user to add items interactively using a keyboard, you probably need a data grid, not a list. Adding editing to list control subitems is not easy, and it would be easier to start from CWnd. Search "MFC Data Grid" to find some open source class libraries that implemented the feature.
If you can afford adding /clr to your program, you can try the data grid classes in Windows Forms using MFC's Windows Form hosting support. You will find a lot more programming resources on data grid classes in Windows Forms than any other third-party MFC data grid class library.
If you use CRichEditCtrl you can set it to word-wrap, take a look at this snippet extracted from:
http://www.tech-archive.net/Archive/Development/microsoft.public.win32.programmer.ui/2004-03/0111.html
(I've derived my own QRichEditCtrl from the MFC CRichEditCtrl,
and here's the relevant code:)
void QRichEditCtrl::SetWordWrap(bool bWrap)
{
RECT r;
GetWindowRect(&r);
CDC * pDC = GetDC();
long lLineWidth = 9999999; // This is the non-wrap width
if (bWrap)
{
lLineWidth = ::MulDiv(pDC->GetDeviceCaps(PHYSICALWIDTH),
1440, pDC->GetDeviceCaps(LOGPIXELSX));
}
SetTargetDevice(*GetDC(), lLineWidth);
}

Infragistics grid "on-demand" appearance

We're using Infragistics grid (most probably, we'll have 8.2 version at the end) and we want to configure row/cells appearances "on-demand" in order to be able to provide sort of "dynamic appearance".
For example, I want some cell to be red or green, depending on its value. We might want to tweak other characteristics as well (font, size, image, etc).
A perfect place to do it would be some event, that happen before a cell gets repainted... But it seems there is no such event in Infragistics...
Or am I wrong? Any help?
Clarification: I'm talking about WinForms Infragistics UltraGrid
I had to do exactly this with the IG WebGrid a few years back, and it was ... shall we say ... painful. However, the WebGrid had the advantage of a single render point -- once the HTML was emitted, we were set!
For dealing with this in WinGrid, I tried a variety of different events, both on the grid and the datasource, and met with abject failure every step of the way. The only event I got to work was Paint, which will likely create a performance issue.
For Paint, here's what I hacked together. I'm not proud of this code, and I likely wouldn't put it in production, but here it is anyway (C#):
private void UltraGrid1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
foreach (UltraGridRow r in UltraGrid1.Rows)
{
foreach (UltraGridCell c in r.Cells)
{
if (c.Text == "foo")
c.Appearance.BackColor = Color.Green;
}
}
}
and VB:
Private Sub UltraGrid1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles UltraGrid1.Paint
For Each r As UltraGridRow In UltraGrid1.Rows
For Each c As UltraGridCell In r.Cells
If c.Text = "foo" Then
c.Appearance.BackColor = Color.Green
End If
Next
Next
End Sub
There is an event. I don't remember exactly what it's called, but it's got to be something like 'DataRowBound' or 'ItemDataBinding', etc..
Also, this article might help.
Not that this has anything to do with your question, but I'd stay away from heavy use of Infragistics controls - they're very heavy and will slow down the page rendering process considerably. Just my $0.02.
We have finally come up with two solutions for that problem.
For some of the dynamic content we use grid elements appearance and reinitialize it "on-demand".
For the extremely resource-critical appearance we use UltraGrid.DrawFilter (see also IUIElementDrawFilter interface).