PDA

View Full Version : GridView header variable access issue



jgates0
10 Mar 2014, 11:50 AM
Hello, I'm working on upgrading our project to GXT 3.1 beta right now and running into one major issue. We use a custom column header that extends from ColumnHeader to add a bit of functionality that isn't there out of the box. We were able to do this in 3.0.0b as the header variable in GridView was protected so we could extend GridView and still have access to the variable to override the initHeader() method and place our custom column header in. Unfortunately it appears in 3.1 beta that the variable was changed from protected to private and therefore we can't access it anymore and insert our custom column header. There is a setColumnHeader method now, but it can't be called from the initHeader() method since the grid is already defined.

Essentially it would make our lives a lot easier if you could change the access of the header variable in GridView back to protected. Would this be possible to change? If not is there any way to work around this issue aside from copying the entire class?

Here is a snippet of the problem we are running into:


public class CustomGridView<M> extends GridView<M> {

...

@Override
protected void initHeader() {
// header is a private variable so we have no access
// getHeader() will work fine, but setColumnHeader(ColumnHeader<M> columnHeader)
// throws an IllegalStateException since the grid is already defined
if (header == null) {
header = new CustomColumnHeader<M>(grid, cm);
}
super.initHeader();
}

Colin Alworth
10 Mar 2014, 12:48 PM
If we made all variables protected (or heck, why not public!) lots of changes would be easier to make, but it also defeats the purpose of having those keywords in the first place. Public means explicitly designed for users of class instances to manipulate directly, protected means expressly designed to be accessible by subclassing, and anything else (package-default or private) indicates that they are *not* part of the api, meaning they could subject to change or have specific constraints about when they can be changed that aren't otherwise expressed with asserts everywhere.

In this case, you shouldn't need to override initHeader at all - the changes made were done to add setColumnHeader and avoid the case where one had to subclass GridView just to change the header, which was silly. That said, if you have a reason you dont want to do it that way, you can still read the current column header from getHeader() - as in 3.0, if the header variable is null, the method will return null.

If you are getting the IllegalStateException, this means that the header has already been defined once and wired into the grid/view, and can't be defined again without presently causing a memory leak. As you may be aware, the grid is somewhat complex, so not every single feature is infinitely customizable - GridView.java is already nearly 3kloc. As a result, we limit certain customizations that appear to be edge cases, like changing out a header without also changing out the entire view (see Grid.reconfigure).

Your code snippet above seems to indicate that all you really want to do is set a custom header - this can be very simply done without any GridView subclass, as our new word wrap grid example (http://www.sencha.com/examples/#ExamplePlace:wordwrapgrid) is doing:


final Grid<Row> g = new Grid<Row>(ls, cm, new WordWrapGridView());
g.getView().setColumnHeader(new WordWrapColumnHeader<Row>(g, cm));
g.getView().setColumnLines(true);

As long as setColumnHeader is invoked before the grid is initially rendered, it can be replaced at will. Once the grid has been rendered, the entire view must be replaced to reliably replace the header (and avoid memory leaks, other partial redraw issues).