Save/ load QuickAccessToolBar - ribbon

I 'm using Microsoft.Windows.Controls.Ribbon, and i would like save and load QuickAccessToolBar.
How I Can find QuickAccessToolBar items, in ribbon control?
This is my idea to save ribbon QuickAccessToolBar
OnClosing application : Get QuickAccessToolBar items, and locaize on Ribbon items. And then serialize
OnLoad : Read serilize object, and add insert items QuickAccessToolBar

Finally i did it!
I'm based on WPF Ribbon Sample to save/load. It used datacontext to localize control on RibbonControl, and i didn't like, so i isued QuickAccessToolBarId to localize the control.
This is the solution:
- OnClosing Application:
I save QuickAccessToolBar, search items on ribbon control by QuickAccessToolBar, and save path. Note: When item is in application menufirst path is -1.A
- OnLoadApplication:
Load items , and seerch on ribbon control by path.
And this is the code:
RibbonHelper:
class RibbonHelper
{
Ribbon ribbon;
public RibbonHelper(Ribbon ribbon)
{
this.ribbon = ribbon;
}
string _qatFileName = "qat.xml";
internal void Save()
{
try
{
SaveQatItems();
}
catch { }
}
internal void Load()
{
try
{
LoadQatItems();
}
catch
{
}
}
#region Save Qat
private void SaveQatItems()
{
QatItemCollection qatItems = GetQatItemsToSave(ribbon.QuickAccessToolBar);
if (qatItems != null)
{
QatItemCollection remainingItems = new QatItemCollection();
remainingItems.AddRange(qatItems);
SaveQatItemsOfApplicationMenu(remainingItems);
SaveQatItemsOfTabs(remainingItems);
SaveQatItems(qatItems);
}
}
private void SaveQatItems(QatItemCollection qatItems)
{
XmlWriter xmlWriter = XmlWriter.Create(_qatFileName);
XamlWriter.Save(qatItems, xmlWriter);
xmlWriter.Close();
}
private void SaveQatItemsOfApplicationMenu(QatItemCollection remainingItems)
{
if (ribbon.ApplicationMenu != null)
{
if (remainingItems != null)
{
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Add(-1);
});
for (int index = 0; index < ribbon.ApplicationMenu.Items.Count && remainingItems.Count > 0; index++)
{
SaveQatItemsAmongChildren(remainingItems, ribbon.ApplicationMenu.Items[index],index);
}
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Clear();
});
}
}
}
private void SaveQatItemsOfTabs(QatItemCollection remainingItems)
{
if (ribbon.Items != null)
{
if (remainingItems != null)
{
for (int tabIndex = 0; tabIndex < ribbon.Items.Count && remainingItems.Count > 0; tabIndex++)
{
RibbonTab tab = ribbon.Items[tabIndex] as RibbonTab;
SaveQatItemsAmongChildren(remainingItems, tab, tabIndex);
}
}
}
}
private void SaveQatItemsAmongChildren(QatItemCollection remainingItems, object control, int controlIndex)
{
if (control == null)
{
return;
}
//AƱaidmos el control index a los pendientes
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Add(controlIndex);
});
SaveQatItemsAmongChildrenInner(remainingItems, control);
//Eliminamos el control index de los pendientes ya que no estan dentro de ese control
remainingItems.ForEach(qat =>
{
int last = qat.ControlIndices.Count - 1;
qat.ControlIndices.RemoveAt(last);
});
}
private void SaveQatItemsAmongChildrenInner(QatItemCollection remainingItems, object parent)
{
SaveQatItemsIfMatchesControl(remainingItems, parent);
if (remainingItems.Count == 0 || IsLeaf(parent))
{
return;
}
int childIndex = 0;
DependencyObject dependencyObject = parent as DependencyObject;
if (dependencyObject != null)
{
IEnumerable children = LogicalTreeHelper.GetChildren(dependencyObject);
foreach (object child in children)
{
SaveQatItemsAmongChildren(remainingItems, child, childIndex);
childIndex++;
}
}
if (childIndex != 0)
{
return;
}
// if we failed to get any logical children, enumerate the visual ones
Visual visual = parent as Visual;
if (visual == null)
{
return;
}
for (childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(visual); childIndex++)
{
Visual child = VisualTreeHelper.GetChild(visual, childIndex) as Visual;
SaveQatItemsAmongChildren(remainingItems, child, childIndex);
}
}
private bool IsLeaf(object element)
{
if ((element is RibbonButton) ||
(element is RibbonToggleButton) ||
(element is RibbonRadioButton) ||
(element is RibbonCheckBox) ||
(element is RibbonTextBox) ||
(element is RibbonSeparator))
{
return true;
}
RibbonMenuItem menuItem = element as RibbonMenuItem;
if (menuItem != null &&
menuItem.Items.Count == 0)
{
return true;
}
return false;
}
private bool SaveQatItemsIfMatchesControl(QatItemCollection remainingItems, object control)
{
bool matched = false;
FrameworkElement element = control as FrameworkElement;
if (element != null)
{
object getQuickAccessToolBarId = RibbonControlService.GetQuickAccessToolBarId(element);
if (getQuickAccessToolBarId != null)
{
int remove = remainingItems.RemoveAll(qat => qat.QuickAccessToolBarIdHashCode == getQuickAccessToolBarId.GetHashCode());
matched = remove > 0;
}
}
return matched;
}
private QatItemCollection GetQatItemsToSave(RibbonQuickAccessToolBar qat)
{
QatItemCollection qatItems = new QatItemCollection();
if (qat != null && qat.Items != null && qat.Items.Count > 0)
{
foreach (var item in qat.Items)
{
FrameworkElement element = item as FrameworkElement;
if (element != null)
{
object getQuickAccessToolBarId = RibbonControlService.GetQuickAccessToolBarId(element);
if (getQuickAccessToolBarId != null)
{
QatItem qatItem = new QatItem(getQuickAccessToolBarId.GetHashCode());
qatItems.Add(qatItem);
}
}
}
}
return qatItems;
}
#endregion
#region load qat
private void LoadQatItems()
{
if (ribbon.QuickAccessToolBar == null)
{
ribbon.QuickAccessToolBar = new RibbonQuickAccessToolBar();
}
QatItemCollection qatItems = GetQatItemsToLoad();
if ((qatItems != null) && (qatItems.Count > 0))
{
SearchInApplicationMenu(qatItems);
SearchInTabs(qatItems);
qatItems.Where(qat => qat.Owner != null).ToList().ForEach(qat =>
{
if (RibbonCommands.AddToQuickAccessToolBarCommand.CanExecute(null, qat.Owner))
{
RibbonCommands.AddToQuickAccessToolBarCommand.Execute(null, qat.Owner);
}
});
}
}
private void SearchInApplicationMenu(QatItemCollection qatItems)
{
if (qatItems != null)
{
int remainingItemsCount = qatItems.Count(qat=>qat.Owner==null);
QatItemCollection matchedItems = new QatItemCollection();
for (int index = 0; index < ribbon.ApplicationMenu.Items.Count && remainingItemsCount > 0; index++)
{
matchedItems.Clear();
matchedItems.AddRange(qatItems.Where(qat => qat.ControlIndices[0] == -1)); //-1 is applicationMenu
//remove -1
matchedItems.ForEach(qat =>
{
qat.ControlIndices.RemoveAt(0);
}
);
object item = ribbon.ApplicationMenu.Items[index];
if (item != null)
{
if (!IsLeaf(item))
{
LoadQatItemsAmongChildren(matchedItems, 0, index, item, ref remainingItemsCount);
}
else
{
LoadQatItemIfMatchesControl(matchedItems, new QatItemCollection(), 0, index, item, ref remainingItemsCount);
}
}
//Add -1
matchedItems.ForEach(qat =>
{
qat.ControlIndices.Insert(0, -1);
});
}
}
}
private void SearchInTabs(QatItemCollection qatItems)
{
int remainingItemsCount = qatItems.Count(qat => qat.Owner == null);
QatItemCollection matchedItems = new QatItemCollection();
for (int tabIndex = 0; tabIndex < ribbon.Items.Count && remainingItemsCount > 0; tabIndex++)
{
matchedItems.Clear();
matchedItems.AddRange(qatItems.Where(qat => qat.ControlIndices[0] == tabIndex));
RibbonTab tab = ribbon.Items[tabIndex] as RibbonTab;
if (tab != null)
{
LoadQatItemsAmongChildren(matchedItems, 0, tabIndex, tab, ref remainingItemsCount);
}
}
}
private void LoadQatItemsAmongChildren(
QatItemCollection previouslyMatchedItems,
int matchLevel,
int controlIndex,
object parent,
ref int remainingItemsCount)
{
if (previouslyMatchedItems.Count == 0)
{
return;
}
if (IsLeaf(parent))
{
return;
}
int childIndex = 0;
DependencyObject dependencyObject = parent as DependencyObject;
if (dependencyObject != null)
{
IEnumerable children = LogicalTreeHelper.GetChildren(dependencyObject);
foreach (object child in children)
{
if (remainingItemsCount == 0)
{
break;
}
QatItemCollection matchedItems = new QatItemCollection();
LoadQatItemIfMatchesControl(previouslyMatchedItems, matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
LoadQatItemsAmongChildren(matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
childIndex++;
}
}
if (childIndex != 0)
{
return;
}
// if we failed to get any logical children, enumerate the visual ones
Visual visual = parent as Visual;
if (visual == null)
{
return;
}
for (childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(visual); childIndex++)
{
if (remainingItemsCount == 0)
{
break;
}
Visual child = VisualTreeHelper.GetChild(visual, childIndex) as Visual;
QatItemCollection matchedItems = new QatItemCollection();
LoadQatItemIfMatchesControl(previouslyMatchedItems, matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
LoadQatItemsAmongChildren(matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
}
}
private void LoadQatItemIfMatchesControl(
QatItemCollection previouslyMatchedItems,
QatItemCollection matchedItems,
int matchLevel,
int controlIndex,
object control,
ref int remainingItemsCount)
{
for (int qatIndex = 0; qatIndex < previouslyMatchedItems.Count; qatIndex++)
{
QatItem qatItem = previouslyMatchedItems[qatIndex];
if (qatItem.ControlIndices[matchLevel] == controlIndex)
{
if (qatItem.ControlIndices.Count == matchLevel + 1)
{
qatItem.Owner = control as Control; ;
remainingItemsCount--;
}
else
{
matchedItems.Add(qatItem);
}
}
}
}
private QatItemCollection GetQatItemsToLoad()
{
try
{
if (File.Exists(_qatFileName))
{
using (XmlReader xmlReader = XmlReader.Create(_qatFileName))
{
QatItemCollection qatItems = (QatItemCollection)XamlReader.Load(xmlReader);
xmlReader.Close();
return qatItems;
}
}
}
catch
{
//Do nothing, return null;
}
return null;
}
#endregion
}
Classes to serialize:
public class QatItem {
public QatItem()
{
}
public QatItem(int qatbIdHashCode)
{
QuickAccessToolBarIdHashCode = qatbIdHashCode;
}
public Int32Collection ControlIndices
{
get
{
if (_controlIndices == null)
{
_controlIndices = new Int32Collection();
}
return _controlIndices;
}
set
{
_controlIndices = value;
}
}
Int32Collection _controlIndices;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int QuickAccessToolBarIdHashCode { get; set; }
//Is only for load
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Control Owner { get; set; }
}
public class QatItemCollection : List<QatItem>
{
}
And this is the code to save/load from window
RibbonHelper helper;
protected override void OnClosing(CancelEventArgs e)
{
helper.Save();
base.OnClosing(e);
}
private void RibbonWindow_Loaded(object sender, RoutedEventArgs e)
{
helper = new RibbonHelper(ribbon);
helper.Load();
}

Related

Xamarin.Forms.Maps - Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))

I followed the Xamarin Tutorial Customizing a Map.
I changed it a bit to be able to draw a route.
public class CustomMap : Map
{
public static readonly BindableProperty RouteCoordinatesProperty =
BindableProperty.Create(nameof(RouteCoordinates), typeof(List<Position>), typeof(CustomMap), new List<Position>(), BindingMode.TwoWay);
public List<Position> RouteCoordinates
{
get { return (List<Position>)GetValue(RouteCoordinatesProperty); }
set { SetValue(RouteCoordinatesProperty, value); }
}
}
The WinPhone 8.1 renderer:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace PROJECT.WinPhone
{
public class CustomMapRenderer : MapRenderer
{
MapControl nativeMap;
CustomMap formsMap;
protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
nativeMap = Control as MapControl;
}
if (e.NewElement != null)
{
formsMap = (CustomMap)e.NewElement;
nativeMap = Control as MapControl;
//UpdatePolyLine();
var coordinates = new List<BasicGeoposition>();
foreach (var position in formsMap.RouteCoordinates)
{
coordinates.Add(new BasicGeoposition() { Latitude = position.Latitude, Longitude = position.Longitude });
}
var polyline = new MapPolyline();
polyline.StrokeColor = Windows.UI.Color.FromArgb(128, 255, 0, 0);
polyline.StrokeThickness = 5;
polyline.Path = new Geopath(coordinates);
nativeMap.MapElements.Add(polyline);
}
}
}
}
polyline.Path = new Geopath(coordinates); throws Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
The problem is that my two others renderer (Android & iOS) works.. Maybe something isn't possible because I work with WinPhone8.1 unlike the tutorial, which is UWP
AndroidRenderer
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace PROJECT.Droid
{
public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback
{
GoogleMap map;
Polyline polyline;
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Xamarin.Forms.View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
((MapView)Control).GetMapAsync(this);
}
UpdatePolyLine();
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (this.Element == null || this.Control == null)
return;
if (e.PropertyName == CustomMap.RouteCoordinatesProperty.PropertyName)
{
UpdatePolyLine();
}
}
private void UpdatePolyLine()
{
if (map != null)
{
if (polyline != null)
{
polyline.Remove();
polyline.Dispose();
}
var polylineOptions = new PolylineOptions();
polylineOptions.InvokeColor(0x66FF0000);
int a = 0;
foreach (var position in ((CustomMap)this.Element).RouteCoordinates)
{
polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
}
polyline = map.AddPolyline(polylineOptions);
}
}
public void OnMapReady(GoogleMap googleMap)
{
map = googleMap;
UpdatePolyLine();
}
}
}
iOSRenderer
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace PROJECT.iOS
{
public class CustomMapRenderer : MapRenderer
{
MKMapView nativeMap;
MKPolylineRenderer polylineRenderer;
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
nativeMap = Control as MKMapView;
nativeMap.OverlayRenderer = null;
}
if (e.NewElement != null)
{
UpdatePolyLine();
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (this.Element == null || this.Control == null)
return;
if (e.PropertyName == CustomMap.RouteCoordinatesProperty.PropertyName)
{
UpdatePolyLine();
}
}
MKOverlayRenderer GetOverlayRenderer(MKMapView mapView, IMKOverlay overlay)
{
if (polylineRenderer == null)
{
polylineRenderer = new MKPolylineRenderer(overlay as MKPolyline);
polylineRenderer.FillColor = UIColor.Blue;
polylineRenderer.StrokeColor = UIColor.Red;
polylineRenderer.LineWidth = 3;
polylineRenderer.Alpha = 0.4f;
}
return polylineRenderer;
}
private void UpdatePolyLine()
{
if (nativeMap != null)
{
var formsMap = ((CustomMap)this.Element);
nativeMap = Control as MKMapView;
nativeMap.OverlayRenderer = GetOverlayRenderer;
CLLocationCoordinate2D[] coords = new CLLocationCoordinate2D[formsMap.RouteCoordinates.Count];
int index = 0;
foreach (var position in formsMap.RouteCoordinates)
{
coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude);
index++;
}
var routeOverlay = MKPolyline.FromCoordinates(coords);
nativeMap.AddOverlay(routeOverlay);
}
}
}
}
After a long time, I found why it didn't works...
If you're doing like me, if you do a HttpRequest to something as Google Direction API, then the result will comes after the first passage in the OnElementChanged().
Because formsMap.RouteCoordinates isn't null but empty, the Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED)) is thrown..
This is the good CustomMapRenderer for PolyLine use
using PROJECT;
using PROJECT.UWP;
using System.Collections.Generic;
using Windows.Devices.Geolocation;
using Windows.UI.Xaml.Controls.Maps;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.UWP;
using Xamarin.Forms.Platform.UWP;
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace PROJECT.UWP
{
public class CustomMapRenderer : MapRenderer
{
MapControl nativeMap;
CustomMap formsMap;
protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
nativeMap = Control as MapControl;
}
if (e.NewElement != null)
{
formsMap = (CustomMap)e.NewElement;
nativeMap = Control as MapControl;
UpdatePolyLine();
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (this.Element == null || this.Control == null)
return;
if (e.PropertyName == CustomMap.RouteCoordinatesProperty.PropertyName)
{
UpdatePolyLine();
}
}
private void UpdatePolyLine()
{
if (formsMap != null && formsMap.RouteCoordinates.Count > 0)
{
List<BasicGeoposition> coordinates = new List<BasicGeoposition>();
foreach (var position in formsMap.RouteCoordinates)
{
coordinates.Add(new BasicGeoposition() { Latitude = position.Latitude, Longitude = position.Longitude });
}
Geopath path = new Geopath(coordinates);
MapPolyline polyline = new MapPolyline();
polyline.StrokeColor = Windows.UI.Color.FromArgb(128, 255, 0, 0);
polyline.StrokeThickness = 5;
polyline.Path = path;
nativeMap.MapElements.Add(polyline);
}
}
}
}

JSP tag library to display MySQL rollup query with grouping and subtotals

I need to display several tables as HTML, using JSP, coming from MySQL GROUP BY a,b,c WITH ROLLUP queries. I'm looking for a good tag library to achieve this. I have found DisplayTag, but it'was last updated in 2008. And I would prefer using the subtotals calculated by MySQL, which seems to be tricky with DisplayTag.
MySQL does subtotals by adding extra rows to the resultset with the group field set to NULL.
Is there a better alternative? Printing the table is important, paging and sorting would be nice but I can live without them. No editing of any kind.
I wrote my own quick-and-dirty tag. Note that it expects the rollup data structure returned by MySQL, haven't tested it with anything else.
Usage example:
<xxx:rollupTable cssClass="data" data="${data}">
<xxx:rollupColumn title="Person" align="left" group="true" fieldName="personName" groupFieldName="personId" tooltipLink="person"/>
<xxx:rollupColumn title="City" align="left" group="true" fieldName="cityName" groupFieldName="cityId" tooltipLink="city"/>
<xxx:rollupColumn title="Price" align="right" format="#,##0.000" fieldName="price"/>
<xxx:rollupColumn title="Amount" align="right" format="#,##0" fieldName="amount"/>
</xxx:rollupTable>
The column tag does not much but adds the column definition to the table tag for later use.
package xxx.tags;
import...
public class RollupTableColumnTag extends SimpleTagSupport {
private String title;
private boolean group = false;
private boolean sum = false;
private String fieldName; // field name to output
private String groupFieldName; // field name to test for rollup level changes
private String align;
private String format;
private String tooltipLink;
private DecimalFormat formatter;
public void doTag() throws IOException, JspTagException {
RollupTableTag parent = (RollupTableTag)findAncestorWithClass(this, RollupTableTag.class);
if (parent == null) {
throw new JspTagException("Parent tag not found.");
}
parent.addColumnDefinition(this);
}
public void setFormat(String format) {
formatter = new DecimalFormat(format);
this.format = format;
}
public DecimalFormat getFormatter() {
return formatter;
}
// other getters and setters are standard, excluded
}
The table tag does the actual hard work:
package xxx.tags;
import ...
public class RollupTableTag extends BodyTagSupport {
protected String cssClass;
protected List<Map> data;
protected List<RollupTableColumnTag> columns;
protected List<Integer> groups;
public void setCssClass(String cssClass) {
this.cssClass = cssClass;
}
public void setData(List data) {
this.data = (List<Map>)data;
}
public int doStartTag() throws JspException {
columns = new ArrayList<RollupTableColumnTag>();
groups = new ArrayList<Integer>();
return EVAL_BODY_BUFFERED;
}
public int doEndTag() throws JspException {
try {
JspWriter writer = pageContext.getOut();
if (data.size() == 0) {
writer.println("<P>No data.</P>");
return EVAL_PAGE;
}
int nLevels = groups.size();
int nNormalRowCount = 0;
boolean[] bStartGroup = new boolean[nLevels];
String[] sSummaryTitle = new String[nLevels];
for (int i=0;i<nLevels;i++) {
bStartGroup[i] = true;
}
writer.println("<TABLE class=\"" + cssClass + "\">");
writer.println("<THEAD><TR>");
for (RollupTableColumnTag column : columns) {
writer.print("<TH");
if (column.getAlign() != null) {
writer.print(" align=\"" + column.getAlign() + "\"");
}
writer.print(">" + column.getTitle() + "</TH>");
}
writer.println("</TR></THEAD>");
writer.println("<TBODY>");
for (Map dataRow : data) {
StringBuffer out = new StringBuffer();
out.append("<TR>");
// grouping columns always come first
String cellClass = null;
for (int i=0;i<nLevels-1;i++) {
if (bStartGroup[i]) {
Object dataField = dataRow.get(columns.get(groups.get(i)).getFieldName());
sSummaryTitle[i] = dataField == null ? "" : dataField.toString();
}
}
int nLevelChanges = 0;
for (int i=0;i<nLevels;i++) {
if (dataRow.get( columns.get(groups.get(i)).getGroupFieldName() ) == null) {
if (i>0) {
bStartGroup[i-1] = true;
}
nLevelChanges++;
}
}
int nTotalLevel = nLevels - nLevelChanges;
if (nLevelChanges == nLevels) { // grand total row
cellClass = "grandtotal";
addCell(out, "Grand Total:", null, cellClass, nLevelChanges);
} else if (nLevelChanges > 0) { // other total row
boolean isOneLiner = (nNormalRowCount == 1);
nNormalRowCount = 0;
if (isOneLiner) continue; // skip one-line sums
cellClass = "total"+nTotalLevel;
for (int i=0;i<nLevels-nLevelChanges-1;i++) {
addCell(out," ",null,cellClass, 1);
}
addCell(out, sSummaryTitle[nLevels-nLevelChanges-1] + " total:", null, cellClass, nLevelChanges+1);
} else { // normal row
for (int i=0;i<nLevels;i++) {
if (bStartGroup[i]) {
RollupTableColumnTag column = columns.get(groups.get(i));
Object cellData = dataRow.get(column.getFieldName());
String displayVal = cellData != null ? cellData.toString() : "[n/a]";
if (column.getTooltipLink() != null && !column.getTooltipLink().isEmpty() && cellData != null) {
String tooltip = column.getTooltipLink();
int dataid = Integer.parseInt(dataRow.get(column.getGroupFieldName()).toString());
displayVal = "<div ajaxtooltip=\"" + tooltip + "\" ajaxtooltipid=\"" + dataid + "\">" + displayVal + "</div>";
}
addCell(out, displayVal, column.getAlign(), null, 1);
} else {
addCell(out," ", null, null, 1);
}
}
for (int i=0;i<nLevels-1;i++) {
bStartGroup[i] = false;
}
nNormalRowCount++;
}
// other columns
for (RollupTableColumnTag column : columns) {
if (!column.isGroup()) {
Object content = dataRow.get(column.getFieldName());
String displayVal = "";
if (content != null) {
if (column.getFormat() != null) {
float val = Float.parseFloat(content.toString());
displayVal = column.getFormatter().format(val);
} else {
displayVal = content.toString();
}
}
addCell(out,displayVal,column.getAlign(),cellClass,1);
}
}
out.append("</TR>");
// empty row for better readability
if (groups.size() > 2 && nLevelChanges == groups.size() - 1) {
out.append("<TR><TD colspan=\"" + columns.size() + "\"> </TD>");
}
writer.println(out);
}
writer.println("</TBODY>");
writer.println("</TABLE>");
} catch (IOException e) {
e.printStackTrace();
}
return EVAL_PAGE;
}
public void addCell(StringBuffer out, String content, String align, String cssClass, int colSpan) {
out.append("<TD");
if (align != null) {
out.append(" align=\"" + align + "\"");
}
if (cssClass != null) {
out.append(" class=\"" + cssClass + "\"");
}
if (colSpan > 1) {
out.append(" colspan=\"" + colSpan + "\"");
}
out.append(">");
out.append(content);
out.append("</TD>");
}
public void addColumnDefinition(RollupTableColumnTag cd) {
columns.add(cd);
if (cd.isGroup()) groups.add(columns.size()-1);
}
}

Metro App CollectionViewSource ObservableCollection Filter

It appears that filtering an ObservableCollection with CollectionViewSource is not possible in WinRT:
See here!
I can filter using LINQ, but how do I get the UI to update if changes that affect the filtered data are made?
I ended up writing my own class to achieve the desired effect:
public class ObservableCollectionView<T> : ObservableCollection<T>
{
private ObservableCollection<T> _view;
private Predicate<T> _filter;
public ObservableCollectionView(IComparer<T> comparer)
: base(comparer)
{
}
public ObservableCollectionView(IComparer<T> comparer, IEnumerable<T> collection)
: base(comparer, collection)
{
}
public ObservableCollectionView(IComparer<T> comparer, IEnumerable<T> collection, Predicate<T> filter)
: base(comparer, collection == null ? new T[] { } : collection)
{
if (filter != null)
{
_filter = filter;
if (collection == null)
_view = new ObservableCollection<T>(comparer);
else
_view = new ObservableCollection<T>(comparer, collection);
}
}
public ObservableCollection<T> View
{
get
{
return (_filter == null ? this : _view);
}
}
public Predicate<T> Filter
{
get
{
return _filter;
}
set
{
if (value == null)
{
_filter = null;
_view = new ObservableCollection<T>(Comparer);
}
else
{
_filter = value;
Fill();
}
}
}
private void Fill()
{
_view = new ObservableCollection<T>(Comparer);
foreach (T item in this)
{
if (Filter(item))
View.Add(item);
}
}
private int this[T item]
{
get
{
int foundIndex = -1;
for (int index = 0; index < View.Count; index++)
{
if (View[index].Equals(item))
{
foundIndex = index;
break;
}
}
return foundIndex;
}
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
if (_filter != null)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (T item in e.NewItems)
if (Filter(item))
View.Add(item);
break;
case NotifyCollectionChangedAction.Move:
break;
case NotifyCollectionChangedAction.Remove:
foreach (T item in e.OldItems)
if (Filter(item))
View.Remove(item);
break;
case NotifyCollectionChangedAction.Replace:
for (int index = 0; index < e.OldItems.Count; index++)
{
T item = (T)e.OldItems[index];
if (Filter(item))
{
int foundIndex = this[item];
if (foundIndex != -1)
View[foundIndex] = (T)e.NewItems[index];
}
}
break;
case NotifyCollectionChangedAction.Reset:
Fill();
break;
}
}
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (_filter != null)
{
// TODO: Implement code for property changes
}
}
}
Not yet perfect. So improvements/suggestions welcomed.
You can now bind this object, directly to a control using the View property.
You need to make sure the filtering changes are observable, so you can set the source of the CollectionViewSource to an ObservableCollection and make the changes on that collection or assign a new Source of the CVS to a new, filtered collection.

null pointer exception at run time

This is my first post here. I am trying to create a singly link list. I am using AtEnd and AtStart methods to insert values at the end or in the beginning of the list and using display method to print all the values. The insertion methods seems to be working fine (at least I think so) but whenever I call display method it shows only the first value and then there is a null pointer exception. For example when I run this code I see only 9 and then there is the NPE despite the fact that I have put a check on the display method for "not null".
class node {
private int data;
private node next;
node() {
}
node(int data) {
this.data = data;
this.next = null;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data=data;
}
public node getNext() {
return next;
}
public void setNext(node next) {
this.next = next;
}
}
public class list extends node {
node head;
list() {
}
public void AtStart(int val) {
node n = new node(val);
if (head == null) {
head=n;
} else {
n.setNext(head);
int temp = head.getData();
head.setData(val);
n.setData(temp);
//n = head;
}
}
public void AtEnd(int val) {
if (head == null) {
node n = new node(val);
head = n;
} else {
node t = head;
for(; t.getNext() != null; ) {
if(t.getNext() == null) {
t.setNext(new node (val));
}
t = t.getNext();
}
}
}
public void display() {
node t = head;
for(; t.getNext() == null;) {
if (t !=null) {
System.out.println(t.getData());
t = t.getNext();
}
}
}
}
public static void main(String args[]) {
list l = new list();
l.AtStart(16);
l.AtEnd(6);
l.AtEnd(36);
l.AtStart(9);
l.AtEnd(22);
l.display();
}
i dont get what your AtStart function does, it should be much simpler:
public void AtStart(int val){
if(head==null){
head=n;
}
else{
head.setnext(head);
head.setData(val);
}
}

How to make the jList selectable inside a jTable

How to make the jList selectable and jScrollPane scrollable inside a jTable.
This is my table code :
private JTable getCalendarTable() {
if (calendarTable == null) {
calendarTable = new JTable() {
public boolean isCellEditable(int nRow, int nCol) {
if (nRow % 2 != 0) {
return true;
} else
return false;
}
};
DefaultTableModel mtblCalendar = (DefaultTableModel) calendarTable
.getModel();
String[] headers = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
"Sat" };
for (int i = 0; i < 7; i++) {
mtblCalendar.addColumn(headers[i]);
}
calendarTable.setCellSelectionEnabled(true);
calendarTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
calendarTable.setRowHeight(60);
mtblCalendar.setColumnCount(7);
mtblCalendar.setRowCount(12);
GregorianCalendar cal = new GregorianCalendar();
realDay = cal.get(GregorianCalendar.DAY_OF_MONTH); // Get day
realMonth = cal.get(GregorianCalendar.MONTH); // Get month
realYear = cal.get(GregorianCalendar.YEAR); // Get year
currentMonth = realMonth; // Match month and year
currentYear = realYear;
refreshCalendar(currentMonth, currentYear);
}
return calendarTable;
}
class tblCalendarRenderer extends JTextArea implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean selected, boolean focused, int row,
int column) {
this.setText(value == null ? "" : value.toString());
this.setLineWrap(true);
this.setWrapStyleWord(true);
if (column == 0 || column == 6) { // Week-end
setBackground(new Color(255, 220, 220));
} else { // Week
setBackground(new Color(255, 255, 255));
}
if (row % 2 == 0) {
if (value != null) {
if (Integer.parseInt(value.toString()) == realDay
&& currentMonth == realMonth
&& currentYear == realYear) { // Today
setBackground(new Color(220, 220, 255));
}
}
} else {
if (value != null) {
// Here is just an test data I want to make sure the jList is working. When
// the date has event, show jList
JList list = new JList(new Object[] { "werwre", "fsdfsd",
"details", "computer", "folder", "computer" });
list.setVisibleRowCount(4);
JScrollPane pane = new JScrollPane(list);
list.setCellRenderer(new Incorenderer());
return pane;
}
}
return this;
}
}
}
The JList and JScrollPanel appeared when the date has event. But the jList was unselectable and the scrollpanel was unscrollable.
You need to use your code that draws a JList in a TableCellRenderer implementation and use it as an editor, i.e.:
class CalendarCellEditor extends AbstractCellEditor implements TableCellEditor {
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
if (value != null) {
// Here is just an test data I want to make sure the jList is
// working. When
// the date has event, show jList
JList list = new JList(new Object[] { "werwre", "fsdfsd",
"details", "computer", "folder", "computer" });
list.setVisibleRowCount(4);
JScrollPane pane = new JScrollPane(list);
list.setCellRenderer(new Incorenderer());
return pane;
} else {
// TODO return whatever you need
return null;
}
}
public Object getCellEditorValue() {
// TODO return whatever you need
return 1;
}
}
And add this editor to your table by overriding the following method in you anonymous inner JTable class:
public TableCellEditor getCellEditor(int row, int column) {
return new CalendarCellEditor();
}