I need to convert a server response from an array to an array of JSON object format.
The rows of data coming fron the server needs to be converted in order for the Kendo UI grid widget to work properly.
I have converted the schema and column definitions into a Json format, but having some difficulty with the actual data rows.
Here's the RAW server response where
1) the "data" array contains the data schema
2) the "rows" array contains the actual values :
{"status":"SUCCESS", "messages":[],
"data":[{"attributes":[{"name":"BookingLocation","type":"string"},{"name":"SUM(CDSStress A:USD 10Y X -1.25)","type":"double"},{"name":"SUM(CDSStress A:USD 10Y X 1.25)","type":"double"},{"name":"SUM(CDSStress A:USD 8Y X 1.25)","type":"double"}],
"rows":[{"id":0,"values":["London",0,0,0]},{"id":1,"values":["Paris",0,0,0]},{"id":2,"values":["Dubai",1564.92711931719,-171.934775655824,-54539.9112355565]},{"id":3,"values":["New York",0,0,0]},{"id":4,"values":["Stockholm",0,0,0]},{"id":5,"values":["World",0,0,0]}]}]}
Essentially I need to pull the "attributes" array, and match them up with the "rows" array - and do this all dynamically for any server response.
Now pulling the schema information from the "attributes" array (within "data"), I can build the schema JSON object dynamically, then plug it into the Kendo grid - something like this :
var myModel = { // sample schema object; actually built dynamically in javascript
"id": "Id",
"fields": {
"BookingCountry": {
"type": "string"
},
"SUM(CDSStress A:USD 10Y X -1.25)": {
"type": "number"
},
"SUM(CDSStress A:USD 10Y X 1.25)": {
"type": "number"
},
"SUM(CDSStress A:USD 8Y X 1.25)": {
"type": "number"
}
}
}
var myColumns = $rootScope.reptWizard.colDefs; // build the columns def
var myData = $rootScope.reptWizard.aggrResults; // convert data rows to JSON object
var ds = {
schema: {
model: myModel
},
vm.mainHierGridOptions = {
dataSource: ds,
columns: myColumns
};
pageSize: 10,
data: myData
};
{
However, the 'myData' object needs to look like this :
[
{ "id": 0,
"BookingCountry": "London",
"SUM(CDSStress A:USD 10Y X -1.25)": 1564.92711,
"SUM(CDSStress A:USD 10Y X 1.25)": -171.9347756,
"SUM(CDSStress A:USD 8Y X 1.25)": -54539.911235
},
{ "id": 0,
"BookingCountry": "Dubai",
"SUM(CDSStress A:USD 10Y X -1.25)": 1564.92711,
"SUM(CDSStress A:USD 10Y X 1.25)": -171.9347756,
"SUM(CDSStress A:USD 8Y X 1.25)": -54539.911235
}
]
As you can see, I need to iterate the "values" array and create a nicely-formatted JSON object with the correct field:value - i.e. "BookingCountry": "London".
Here's a function I created to format the myCols var :
function buildDynamicColumnDefs(fieldAttribs) {
// creates an array of Json objects; to be used as input to the Grid's 'columns' property
var numAttribs = fieldAttribs.length;
var myType = '';
var myCols = [];
if (numAttribs > 0) {
_.each(fieldAttribs, function (field) {
myCols.push({field: field, title: field});
});
}
return myCols;
}
and another function to create the myModel var :
function buildDynamicDataSourceModel(fieldAttribs) {
// creates a valid Json object {name:value} to be used in Kendo Grid DataSource
var jsonExample = {
"BookingLocation": { "type": "string" },
"SUM(CDSStress A:USD 10Y X -1.25)": { "type": "number" },
"SUM(CDSStress A:USD 10Y X 1.25)": { "type": "number" },
"SUM(CDSStress A:USD 8Y X 1.25)": { "type": "number" }
};
var numAttribs = fieldAttribs.length;
var myType = '';
var myFields = {};
if (numAttribs > 0) {
_.each(fieldAttribs, function (field) {
myType = (field.type == "double" ? "number" : field.type); // 'number' is valid type for Kendo Grid schema
myFields[field.name] = { type: myType };
});
}
var myModel = {
id: "Id",
fields: myFields
/*fields: {
dimensions: { type: "string" },
values: { editable: false, type: "number" }
}*/
};
return myModel;
}
But now I need to create the buildJSONGridData(), and your help is greatly appreciated.
regards,
Bob
Here is a function I used to help in exporting a Kendo UI Grid to pdf and Reporting services . This function takes the client blob values (title,columns,data) and build a collection ofg strongly types objects. You could probally do the same on the client side. Notice where the if(dataObject!=null) is located that is where the data json objects are deserialzed. Hope it helps.
//------------------------------------------------------------------------------------------------------------------------------------
private CustomReportData CreateReportFromKendoData(string title, string columns, string data)
{
List<int> _ignoredColumns=new List<int>();
var columnObject = (columns == null) ? null : JsonConvert.DeserializeObject<dynamic>(columns);
var dataObject = (data == null) ? null : JsonConvert.DeserializeObject<dynamic>(data);
CustomReportData reportData = new CustomReportData();
reportData.ReportTitle = title;
if (columnObject != null)
for (int columnCount = 0; columnCount < columnObject.Count; columnCount++)
{
string fieldName = columnObject[columnCount].title == null ? columnObject[columnCount].field.ToString() : columnObject[columnCount].title.ToString();
if (ShouldDisplay(columnObject[columnCount].ToString()))
{
//IF WIDTH IS NULL THEN COLUMNS ARE EVNLY SPREAD THIS WILL BOMB
reportData.Columns.Add(new CustomReportColumn
{
FieldName = fieldName,
DataType = "",
Width = (columnObject[columnCount].width!=null)?this.GetFirstNumeric(columnObject[columnCount].width.ToString(), 250) :250
});
}
else
_ignoredColumns.Add(columnCount);
}
if (dataObject != null)
{
bool hasGrouping = dataObject[0].value != null;
for (int rowCount = 0; rowCount < dataObject.Count; rowCount++)
{
if (hasGrouping)
{
CustomReportGroup group = new CustomReportGroup();
group.GroupName = dataObject[rowCount].field.ToString();
group.GroupValue = ApplyFormat(dataObject[rowCount].value.ToString(),null);
this.RecursiveProcessGroups(group, dataObject[rowCount].items.ToString(), columnObject.ToString(),_ignoredColumns);
reportData.Groups.Add(group);
}
else
{
CustomReportDataRow row = new CustomReportDataRow();
for (int columnCount = 0; columnCount < columnObject.Count; columnCount++)
{
if (!_ignoredColumns.Contains(columnCount))
{
string format = (columnObject[columnCount].format == null ? "" : columnObject[columnCount].format.ToString());
string value = dataObject[rowCount][columnObject[columnCount].field.ToString()].ToString();
value = ApplyFormat(value, format);
row.Fields.Add(value);
}
}
reportData.DataRows.Add(row);
}
}
reportData.GroupDepth = this.GetGroupDepth(reportData.Groups);
}
return reportData;
}
Recursive function for group nesting
//------------------------------------------------------------------------------------------------------------------------------------
private void RecursiveProcessGroups(CustomReportGroup parentGroup, string items, string columns, List<int> ignoredColumns)
{
var groupItems = (items == null) ? null : JsonConvert.DeserializeObject<dynamic>(items);
var columnObject = (columns == null) ? null : JsonConvert.DeserializeObject<dynamic>(columns);
bool hasGrouping = groupItems[0]["value"] != null;
if (hasGrouping)
{
for (int rowCount = 0; rowCount < groupItems.Count; rowCount++)
{
CustomReportGroup group = new CustomReportGroup();
group.GroupName = groupItems[rowCount].field.ToString();
group.GroupValue = ApplyFormat(groupItems[rowCount].value.ToString(),null);
parentGroup.Groups.Add(group);
RecursiveProcessGroups(group, groupItems[rowCount].items.ToString(), columns.ToString(), ignoredColumns);
}
}
else
{
for (int groupItemCount = 0; groupItemCount < groupItems.Count; groupItemCount++)
{
CustomReportDataRow row = new CustomReportDataRow();
for (int columnCount = 0; columnCount < columnObject.Count; columnCount++)
if (!ignoredColumns.Contains(columnCount))
{
string value = groupItems[groupItemCount][columnObject[columnCount].field.ToString()].ToString();
string format = (columnObject[columnCount].format == null ? "" : columnObject[columnCount].format.ToString());
value = ApplyFormat(value, format);
row.Fields.Add(value);
}
parentGroup.DataRows.Add(row);
}
}
}
Domain Objects
public class CustomReportColumn
{
public string FieldName { get; set; }
public string DataType { get; set; }
public float Width { get; set; }
}
public class CustomReportColumns : List<CustomReportColumn> { }
public class CustomReportDataRow
{
public CustomReportDataRow()
{
Fields = new List<string>();
}
public List<string> Fields { get; set; }
}
public class CustomReportDataRows : List<CustomReportDataRow> { }
public class CustomReportGroup
{
public CustomReportGroup()
{
DataRows = new CustomReportDataRows();
Groups = new CustomReportGroups();
}
public string GroupName { get; set; }
public string GroupValue { get; set; }
public CustomReportGroups Groups { get; set; }
public CustomReportDataRows DataRows { get; set; }
}
public class CustomReportGroups : List<CustomReportGroup> { }
public class CustomReportData
{
public CustomReportData()
{
Groups = new CustomReportGroups();
Columns = new CustomReportColumns();
DataRows = new CustomReportDataRows();
}
public int GroupDepth { get; set; }
public CustomReportColumns Columns { get; set; }
public CustomReportGroups Groups { get; set; }
public CustomReportDataRows DataRows { get; set; }
public string ReportTitle { get; set; }
}
PDF Conversion
using iTextSharp.text;
using iTextSharp.text.pdf;
using Svg;
public class PDFServiceiTextSharp:IPDFService
{
private int _GroupDepth=0;
private int _ColumnCount = 0;
//-----------------------------------------------------------------------------------------------------------------------------------------
public byte[] RenderCustomReport(CustomReportData data)
{
try
{
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("INMEMORYPDF.pdf", 1000000))
{
PDFPageMargins margins = new PDFPageMargins(10, 10, 10, 10);
_GroupDepth = data.GroupDepth;
_ColumnCount = data.Columns.Count;
float _pageWidth = this.GetPageWidth(data.Columns, margins);
var document=new Document((_pageWidth>540)?PageSize.A4.Rotate(): PageSize.A4, margins.Left,margins.Right, margins.Top, margins.Bottom);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
PdfWriter.GetInstance(document, stream);
document.Open();
var pdfTable = new PdfPTable(_ColumnCount + _GroupDepth);
int[] columnWidths = new int[_ColumnCount + _GroupDepth];
for(int x=0;x<_GroupDepth;x++)
columnWidths[x]=3;
for(int y=0;y<data.Columns.Count;y++)
columnWidths[_GroupDepth + y] = Convert.ToInt32(data.Columns[y].Width);
pdfTable.SetWidths(columnWidths);
pdfTable.DefaultCell.Padding = 3;
pdfTable.DefaultCell.BorderWidth = 1;
pdfTable.DefaultCell.HorizontalAlignment = Element.ALIGN_TOP;
this.CreateHeaderColumns(pdfTable, data.Columns);
pdfTable.HeaderRows = 1;
pdfTable.DefaultCell.BorderWidth = 1;
if (data.Groups.Count > 0)
this.CreateGroupData(pdfTable, data.Groups, 0);
else
for (int x = 0; x < data.DataRows.Count; x++)
this.CreateDetailColumns(pdfTable, data.DataRows[x]);
document.Add(pdfTable);
document.Close();
}
byte[] content;
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader rdr = new BinaryReader(stream);
content = new byte[mmf.CreateViewStream().Length];
rdr.Read(content, 0, (int)mmf.CreateViewStream().Length);
}
return content;
}
}
catch
{
throw;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
public float GetPageWidth(CustomReportColumns columns, PDFPageMargins margins)
{
float width=0;
foreach (CustomReportColumn c in columns)
width += c.Width;
return width + margins.Left + margins.Right + (_GroupDepth * 3);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateHeaderColumns(PdfPTable table,CustomReportColumns columns)
{
Font headerFont = this.GetHeaderFont();
for(int gc=0;gc<_GroupDepth;gc++)
{
PdfPCell cell = new PdfPCell(new Phrase("", headerFont));
cell.BorderWidth=0;
table.AddCell(cell);
}
for (int x = 0; x < columns.Count; x++)
{
PdfPCell cell = new PdfPCell(new Phrase(columns[x].FieldName, headerFont));
cell.BorderColor = new BaseColor(100, 149, 237);
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.BorderWidth=0.75f;
cell.Border = Rectangle.BOTTOM_BORDER | Rectangle.TOP_BORDER | Rectangle.RIGHT_BORDER | Rectangle.LEFT_BORDER;
cell.PaddingBottom = 10;
cell.PaddingLeft = 3;
cell.PaddingRight = 3;
cell.PaddingTop = 10;
table.AddCell(cell);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateGroupData(PdfPTable table, CustomReportGroups parentgroups, int groupDepth)
{
if ((parentgroups == null)||(parentgroups.Count==0))
return;
groupDepth++;
foreach (CustomReportGroup group in parentgroups)
{
this.CreateGroupHeader(table, group, groupDepth);
for (int x = 0; x < group.DataRows.Count; x++)
this.CreateDetailColumns(table, group.DataRows[x]);
CreateGroupData(table, group.Groups, groupDepth);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateDetailColumns(PdfPTable table, CustomReportDataRow row)
{
Font detailFont = this.GetDetailFont();
for (int gc = 1; gc <= _GroupDepth; gc++)
{
BaseColor groupColor = this.GetGroupHeaderColor(_GroupDepth);
PdfPCell cell = new PdfPCell(new Phrase("", detailFont));
cell.BackgroundColor = groupColor;
cell.BorderColor = groupColor;
cell.BorderWidth = 0.75f;
table.AddCell(cell);
}
for (int x = 0; x < row.Fields.Count; x++)
{
PdfPCell cell = new PdfPCell(new Phrase(row.Fields[x], detailFont));
cell.BorderColor = new BaseColor(211, 211, 211);
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.BorderWidth = 0.75f;
cell.Border = Rectangle.BOTTOM_BORDER | Rectangle.TOP_BORDER | Rectangle.RIGHT_BORDER | Rectangle.LEFT_BORDER;
cell.PaddingBottom = 1;
cell.PaddingLeft = 3;
cell.PaddingRight = 3;
cell.PaddingTop = 1;
table.AddCell(cell);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateGroupHeader(PdfPTable table, CustomReportGroup group, int depth)
{
Font detailFont = this.GetDetailFont();
for (int gc = 1; gc <= _GroupDepth; gc++)
{
BaseColor depthColor = this.GetGroupHeaderColor(depth);
PdfPCell ecell = new PdfPCell(new Phrase("", detailFont));
ecell.BackgroundColor = depthColor;
ecell.BorderColor = depthColor;
ecell.BorderWidth = 0.75f;
table.AddCell(ecell);
}
BaseColor groupColor = this.GetGroupHeaderColor(depth);
PdfPCell cell = new PdfPCell(new Phrase( group.GroupValue, detailFont));
cell.Colspan = _ColumnCount + ((_GroupDepth - depth));
cell.BorderColor = groupColor;
cell.BackgroundColor = groupColor;
cell.HorizontalAlignment = Element.ALIGN_LEFT;
cell.BorderWidth = 0.75f;
cell.Border = Rectangle.BOTTOM_BORDER | Rectangle.TOP_BORDER | Rectangle.RIGHT_BORDER | Rectangle.LEFT_BORDER;
cell.PaddingBottom = 3;
cell.PaddingLeft = 3;
cell.PaddingRight = 3;
cell.PaddingTop = 3;
table.AddCell(cell);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private Font GetHeaderFont()
{
return FontFactory.GetFont("Arial", 10, Font.BOLD, BaseColor.BLACK);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private Font GetDetailFont()
{
return FontFactory.GetFont("Arial", 8, Font.NORMAL, BaseColor.BLACK);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private BaseColor GetGroupHeaderColor(int groupDepth)
{
switch (groupDepth)
{
case 1: return new BaseColor(211,211,211);
case 2: return new BaseColor(100, 149, 237);
case 3: return new BaseColor(255,165,0);
case 4: return new BaseColor(169,169,169);
case 5: return new BaseColor(211, 211, 211);
default: return new BaseColor(211, 211, 211);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
public void MergeFiles(System.Collections.Generic.List<string> sourceFiles, string destinationFile)
{
Document document=null;
if (System.IO.File.Exists(destinationFile))
System.IO.File.Delete(destinationFile);
try
{
PdfCopy writer = null;
int numberOfPages=0;
foreach(string sourceFile in sourceFiles)
{
PdfReader reader = new PdfReader(sourceFile);
reader.ConsolidateNamedDestinations();
numberOfPages = reader.NumberOfPages;
if(document==null)
{
document = new Document(reader.GetPageSizeWithRotation(1));
writer = new PdfCopy(document, new FileStream(destinationFile, FileMode.Create));
document.Open();
}
for (int x = 1;x <= numberOfPages;x++ )
{
if (writer != null)
{
PdfImportedPage page = writer.GetImportedPage(reader, x);
writer.AddPage(page);
}
}
PRAcroForm form = reader.AcroForm;
if (form != null && writer != null)
{
writer.CopyAcroForm(reader);
}
}
}
catch
{
throw;
}
finally
{
if (document != null && document.IsOpen())
document.Close();
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
public byte[] RenderReportFromSVG(string svgFileContents)
{
System.Drawing.Bitmap _bitmap=null;
byte[] byteArray = Encoding.ASCII.GetBytes(svgFileContents);
using (var stream = new MemoryStream(byteArray))
{
XmlDocument xdoc=new XmlDocument();
xdoc.LoadXml(svgFileContents);
var svgDocument = SvgDocument.Open(xdoc);
_bitmap = svgDocument.Draw();
}
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("INMEMORYPDF.pdf", 1000000))
{
PDFPageMargins margins = new PDFPageMargins(10, 10, 10, 10);
float _pageWidth = margins.Left + margins.Right + _bitmap.Width;
var document = new Document((_pageWidth > 540) ? PageSize.A4.Rotate() : PageSize.A4, margins.Left, margins.Right, margins.Top, margins.Bottom);
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
PdfWriter.GetInstance(document, stream);
document.Open();
iTextSharp.text.Image pdfImage = iTextSharp.text.Image.GetInstance(_bitmap, System.Drawing.Imaging.ImageFormat.Bmp);
var pdfTable = new PdfPTable(1);
pdfTable.SetWidths(new int[]{_bitmap.Width});
pdfTable.DefaultCell.HorizontalAlignment = Element.ALIGN_TOP;
PdfPCell cell = new PdfPCell(pdfImage);
//cell.FixedHeight = fixedHeight;
cell.HorizontalAlignment = Element.ALIGN_CENTER;
cell.VerticalAlignment = Element.ALIGN_MIDDLE;
//img.ScaleAbsolute(200, fixedHeight);
pdfTable.AddCell(cell);
document.Add(pdfTable);
document.Close();
}
byte[] content;
using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
BinaryReader rdr = new BinaryReader(stream);
content = new byte[mmf.CreateViewStream().Length];
rdr.Read(content, 0, (int)mmf.CreateViewStream().Length);
}
return content;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
}
Finally the ExcelService to render grid to excel with column groupings
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
public class ExcelServiceNPOI:IExcelService
{
//-----------------------------------------------------------------------------------------------------------------------------------------
public byte[] RenderCustomReport(CustomReportData data)
{
try
{
if (data == null)
throw new ArgumentNullException("Report data cannot be null");
HSSFWorkbook workBook = new HSSFWorkbook();
ISheet sheet = workBook.CreateSheet(data.ReportTitle);
if (data.Groups.Count > 0)
{
int maxDepth = data.GroupDepth;// this.GroupDepth(data.Groups, 0);
this.CreateColumnHeader(sheet,maxDepth, data.Columns );
this.CreateGroupData(sheet, data.Groups, 0, maxDepth);
}
else
{
this.CreateColumnHeader(sheet, data.Columns);
this.CreateRowData(sheet, data.DataRows);
}
this.SetColumnWidth(sheet, data.Columns);
sheet.CreateFreezePane(0, 1);
MemoryStream ms = new MemoryStream();
workBook.Write(ms);
return ms.ToArray();
}
catch
{
throw;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateColumnHeader(ISheet sheet,CustomReportColumns columns)
{
this.CreateColumnHeader(sheet, 0, columns);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateColumnHeader(ISheet sheet, int columnOffset, CustomReportColumns columns )
{
if (columns == null || columns.Count == 0)
return;
IRow headerRow = sheet.CreateRow(0);
int colCount = columnOffset;
foreach (CustomReportColumn column in columns)
{
headerRow.CreateCell(colCount).SetCellValue(column.FieldName);
colCount++;
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateGroupData(ISheet sheet, CustomReportGroups parentgroups,int groupDepth, int maxDepth)
{
if (parentgroups == null)
return;
groupDepth++;
foreach (CustomReportGroup group in parentgroups)
{
CustomReportDataRow groupHeader = new CustomReportDataRow();
groupHeader.Fields.Add(group.GroupValue);
this.CreateRowData(sheet,groupDepth-1, groupHeader);
int groupBeginRowNum = sheet.LastRowNum+1;
this.CreateRowData(sheet,maxDepth, group.DataRows);
CreateGroupData(sheet,group.Groups, groupDepth, maxDepth);
sheet.GroupRow(groupBeginRowNum, sheet.LastRowNum);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateRowData(ISheet sheet, int startColumnIndex, CustomReportDataRow row)
{
int colNum = startColumnIndex;
IRow newRow = sheet.CreateRow(sheet.LastRowNum + 1);
foreach (string field in row.Fields)
newRow.CreateCell(colNum++).SetCellValue(field);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateRowData(ISheet sheet, CustomReportDataRows rows)
{
CreateRowData(sheet, 0, rows);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void CreateRowData(ISheet sheet, int startColumnIndex, CustomReportDataRows rows)
{
foreach (CustomReportDataRow row in rows)
{
int colNum = startColumnIndex;
IRow newRow = sheet.CreateRow(sheet.LastRowNum + 1);
foreach (string field in row.Fields)
newRow.CreateCell(colNum++).SetCellValue(field);
}
}
//-----------------------------------------------------------------------------------------------------------------------------------------
private void SetColumnWidth(ISheet sheet, CustomReportColumns columns)
{
if (columns == null || columns.Count == 0)
return;
for (int x = 0; x < columns.Count;x++ )
sheet.AutoSizeColumn(x);
}
//-----------------------------------------------------------------------------------------------------------------------------------------
}
Feel free to use it. It works with the latest version of Kendo. I have also added a function RenderReportFromSVG() It will print a Kendo Chart to pdf using chart.svgContents
How do I port this cocos2d-iphone code to cocos2d-x?
(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
switch ([allTouches count]) {
case 1:
{
UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
switch([touch tapCount])
{
case 1:
// 单击!
break;
case 2:
//Double tap.
// 双击!
break;
}
break;
}
}
There is no function to implement this,we can implement this by test the tick between two clicks.In general,the time interval of double click is between 250ms~300ms.Use this to get the system's current number of milliseconds
long millisecondNow()
{
struct cc_timeval now;
CCTime::gettimeofdayCocos2d(&now, NULL);
return (now.tv_sec * 1000 + now.tv_sec / 1000);
}
In MyScene.h, declare:
int tapCount;
Touch lastTouch;
void singleTap(float deltaTime);
Then in MyScene.cpp:
bool MyScene::onTouchBegan(Touch* touch, Event* event)
{
++tapCount;
lastTouch = *touch;
if (tapCount == 1) {
this->schedule(schedule_selector(MyScene::singleTap), 0.25, 1, 0);
}
else {
this->unschedule(schedule_selector(MyScene::singleTap));
tapCount = 0;
printf("\n\ndouble tap\n\n");
}
return true;
}
void MyScene::singleTap(float deltaTime)
{
this->unschedule(schedule_selector(LevelScene::singleTap));
tapCount = 0;
printf("\n\nsingle tap\n\n");
}
You can then access lastTouch in singleTap or your doubleTap method. If you don't need lastTouch to be a Touch object, you can use a Vec2 and set the coordinates. Note that the timer interval (0.25) is more accurate on the device. There is a lag in the simulator since the interval isn't actually wall-clock time.
You can do like this
void HelloWorld::callback1()
{
_tapCount = 0;
}
void HelloWorld::menuCloseCallback(Ref* pSender)
{
_tapCount = _tapCount + 1;
if (_tapCount == 1)
{
DelayTime* delayAction = DelayTime::create(0.3);
CallFunc*resetAction = CallFunc::create(CC_CALLBACK_0(HelloWorld::callback1, this));
Sequence *seq = Sequence::create(delayAction, resetAction, NULL);
this->runAction(seq);
}
else{
log("double tap");
};
}
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();
}