/// <summary> /// Format the hyperlink for a MobiusDataType object /// </summary> /// <param name="qc"></param> /// <param name="mdt"></param> /// <returns></returns> public string FormatHyperlink( CellInfo ci) { MobiusDataType mdt = ci.DataValue as MobiusDataType; int dri = ci.DataRowIndex; DataTableMx dt = Qm.DataTable; DataRowMx dr = null; if (dri >= 0 && dri < dt.Rows.Count) { dr = dt.Rows[dri]; } FormattedFieldInfo ffi = FormatField(ci.Rt, ci.TableIndex, ci.Rfld, ci.FieldIndex, dr, dri, mdt, -1, false); string hyperlink = ffi.Hyperlink; return(hyperlink); }
/// <summary> /// Start async call to get image if not already in progress /// </summary> /// <param name="ci"></param> /// <param name="dr"></param> /// <param name="listSourceRowIndex"></param> /// <param name="fieldValue"></param> /// <param name="imageMx"></param> /// <param name="callId"></param> private void GetImageBitmapAsync(CellInfo ci, DataRowMx dr, int listSourceRowIndex, object fieldValue, ImageMx imageMx, int callId) { if (!imageMx.IsRetrievingValue) // start retrieve if not already started { //if (Debug) ClientLog.Message("Dispatching async callId: " + callId); imageMx.IsRetrievingValue = true; GetImageBitmapDelegate d = new GetImageBitmapDelegate(GetImageBitmap); d.BeginInvoke(ci, dr, listSourceRowIndex, fieldValue, imageMx, callId, new AsyncCallback(ImageBitmapRetrieved), null); return; } else { return; } }
void AddRow( DataTableMx dt, string t1, string t2, int cpdCount) { int voLen = dt.Columns.Count; object[] vo = new object[voLen]; vo[2] = t1; vo[3] = t1; vo[4] = t2; vo[5] = cpdCount; DataRowMx dr = dt.NewRow(); dr.ItemArrayRef = vo; // copy ref for efficiency since vo won't be changed dt.Rows.Add(dr); return; }
/// <summary> /// Do Generic display of a list of structures /// </summary> /// <param name="title"></param> /// <param name="cidLabel"></param> /// <param name="structLabel"></param> /// <param name="structures"></param> public static void DisplayStructures( string title, string cidLabel, string structLabel, List <MoleculeMx> structures, MoleculeGridPanel gridPanel, bool embedDataInQuery) { QueryManager qm = null; MetaTable mt = MetaTableCollection.GetWithException("Generic_Structure_Table"); mt.MetaBrokerType = MetaBrokerType.NoSql; Query q = ToolHelper.InitEmbeddedDataToolQuery(mt); QueryTable qt = q.Tables[0]; qt.Label = title; qt.GetQueryColumnByName("CompoundId").Label = cidLabel; qt.GetQueryColumnByName("Structure").Label = structLabel; DataTableMx dt = q.ResultsDataTable as DataTableMx; for (int mi = 0; mi < structures.Count; mi++) { MoleculeMx cs = structures[mi]; DataRowMx dr = dt.NewRow(); string cid = cs.Id; if (Lex.IsUndefined(cid)) { cid = (mi + 1).ToString(); } dr[qt.Alias + ".CompoundId"] = new CompoundId(cid); dr[qt.Alias + ".Structure"] = cs; dt.Rows.Add(dr); } DisplayData(q, dt, gridPanel, embedDataInQuery); return; }
/// <summary> /// Construct /// </summary> /// <param name="row"></param> /// <param name="action"></param> public DataRowMxChangeEventArgs(DataRowMx row, DataRowAction action) { Row = row; Action = action; }
/// <summary> /// Create and execute the drill down query /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void BuildAndRunDrillDownQuery(object sender, PivotCellEventArgs e) { object o; PivotDrillDownDataSource ds = e.CreateDrillDownDataSource(); if (ds.RowCount <= 0) { return; // no data } Query q2 = Qm.Query.Clone(); q2.ShowGridCheckBoxes = false; // Build name for drilldown from row and column fields values string txt = ""; PivotGridField[] rf = e.GetRowFields(); PivotGridField[] ca = e.GetColumnFields(); Array.Resize(ref rf, rf.Length + ca.Length); Array.Copy(ca, 0, rf, rf.Length - ca.Length, ca.Length); foreach (PivotGridField f in rf) { o = e.GetFieldValue(f); if (o != null && o.ToString() != "") { if (txt != "") { txt += ", "; } txt += o.ToString(); } } if (e.ColumnValueType == PivotGridValueType.GrandTotal || e.RowValueType == PivotGridValueType.GrandTotal) { txt += " Grand Total"; } else if (e.ColumnValueType == PivotGridValueType.Total || e.RowValueType == PivotGridValueType.Total) { txt += " Total"; } q2.UserObject.Name = txt; // Create DataTable containing drill down data DataTableMx dt2 = DataTableManager.BuildDataTable(q2); for (int ri = 0; ri < ds.RowCount; ri++) { // copy rows over DataRowMx dr2 = dt2.NewRow(); object[] vo = dr2.ItemArrayRef; // get ref to the item array for (int ci = 0; ci < dt2.Columns.Count; ci++) { //if (ci == 14) ci = ci; // debug vo[ci] = ds.GetValue(ri, ci); // direct copy into ItemArray } dt2.Rows.Add(dr2); } QueryManager qm2 = ToolHelper.SetupQueryManager(q2, dt2); qm2.ResultsFormat.OutputFormContext = OutputFormContext.Popup; PopupGrid pug = new PopupGrid(qm2); MoleculeGridPanel.ConfigureAndShow(qm2, pug); return; }
/// <summary> /// Call any data changed event handlers for both the IList and DataTable interfaces /// </summary> /// <param name="listChangedType"></param> /// <param name="row"></param> /// <param name="rowIndex"></param> internal void CallDataChangedEventHandlers( ListChangedType listChangedType, DataRowMx row, int rowIndex) { if (!_dataChangedEventHandlersEnabled || !_dataChangedEventHandlersExist) { return; } if (!row._inRowList && listChangedType != ListChangedType.ItemDeleted) { return; // no events if not in the list yet } if (rowIndex < 0) // get index if not supplied { rowIndex = Rows.GetRowIndex(row); // Note: slow } //DebugLog.Message("CallDataChangedEventHandlers " + GetRowIndex(row)); try { if (_listChangedEventHandlers != null && _listChangedEventHandlersCount > 0) // call any IBindingList ListChanged event handlers { ListChangedHandlerCalls++; ListChangedEventArgs ev = new ListChangedEventArgs(listChangedType, rowIndex); _listChangedEventHandlers(this, ev); } if (_rowChangedEventHandlers != null && _rowChangedEventHandlersCount > 0) // call any DataRowMx changed event handlers { RowChangedHandlerCalls++; DataRowAction action; if (listChangedType == ListChangedType.ItemAdded) { action = DataRowAction.Add; } else if (listChangedType == ListChangedType.ItemChanged) { action = DataRowAction.Change; } else if (listChangedType == ListChangedType.ItemDeleted) { action = DataRowAction.Delete; } else { throw new Exception("Unsupported ListChangeType: " + listChangedType); } DataRowMxChangeEventArgs ea = new DataRowMxChangeEventArgs(row, action); _rowChangedEventHandlers(this, ea); } } catch (Exception ex) { ListChangedHandlerCallErrors++; // ignore any errors return; //if (Lex.Contains(ex.Message, "enumeration operation may not execute") && Lex.Contains(ex.StackTrace.ToString(), "UpdateVisibleCardCaptions()")) //{ // ListChangedHandlerCallErrors++; // return; // ignore for now //} //else throw new Exception(ex.Message, ex); // pass it up } return; }
/// <summary> /// Gets the value of the associated ItemArray entry /// </summary> /// <param name="component"></param> /// <returns></returns> public override object GetValue(object component) { DataRowMx row = component as DataRowMx; return(row[_dataColumn.Ordinal]); }
/// <summary> /// Handle conversion of Mobius custom data types between the grid and the underlying DataSet /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void ProcessCustomUnboundColumnDataEvent(object sender, CustomColumnDataEventArgs e) { MobiusDataType mdt = null; FormattedFieldInfo ffi = null; bool formatted = false; NumberMx numberEx; StringMx stringEx; ImageMx imageMx; DateTimeMx dateTimeEx; DataRowMx dr = null; BandedGridView mbgv; int nonNullDri; string debugMsg; if (DebugMx.False) // fillValuesImmediately debug test { e.Value = "XXX"; return; } DateTime t0 = DateTime.Now; int callId = ++UnboundCalls; // get id for this call if (sender is BandedGridView) { mbgv = sender as BandedGridView; } if (Grid.DataSource == null) { return; } CellInfo ci = Grid.GetDataTableCellInfo(e.ListSourceRowIndex, e.Column); //if (e.ListSourceRowIndex == 2 && ci.DataRowIndex == 1) e = e; // debug //if (ci.Mc.DataType == MetaColumnType.CompoundId && ci.DataRowIndex > 0) ci = ci; // debug //DebugLog.Message("CustomUnboundColumnData " + ci.DataRowIndex + ", " + ci.DataColIndex + ", " + ci.DataValue.ToString()); if (ci.Rfld == null) { return; } QueryManager qm = Grid.QueryManager; ResultsFormatter fmtr = qm.ResultsFormatter; ResultsFormat rf = qm.ResultsFormat; if (e.ListSourceRowIndex == GridControl.NewItemRowHandle || e.ListSourceRowIndex >= Qm.DataTable.Rows.Count) // new row being created { if (NewRow == null) { NewRow = Qm.DataTable.NewRow(); } dr = NewRow; } else if (e.ListSourceRowIndex >= 0 && ci.DataRowIndex >= 0) // row exist in DataTable (i.e. not new row) { AdjustDataRowToRender(ci); if (ci.DataRowIndex >= 0) { dr = DataTable.Rows[ci.DataRowIndex]; if (ci.DataRowIndex == 0) { } } } else { if (DebugDetails) { ClientLog.Message("Fail 1"); } return; // something else, ignore } // Store edited data for unbound column in DataTable if (e.IsSetData) { SetGridData(e, ci); return; } else if (!e.IsGetData) { return; // just return if not GetData as expected } // Get data from underlying unbound dataset & return in format for grid //if (ci.Mc.DataType == MetaColumnType.Structure) ci = ci; // debug //if (ci.Mc.DataType == MetaColumnType.String) ci = ci; // debug //if (ci.DataValue is StringEx && ((StringEx)ci.DataValue).Value == " ") ci = ci; // debug UnboundGets++; if (dr == null) { e.Value = null; if (DebugDetails) { ClientLog.Message("Fail 2"); // debug } return; } if (Dtm.IsRetrievingDataMessageRow(dr) && ci.Mc != null && !ci.Mc.IsGraphical) { //if (ci.Mc.IsKey) // show retrieving data message for key field e.Value = "Retrieving data..."; return; } object fieldValue = dr[ci.DataColIndex]; if (DebugDetails && fieldValue is MoleculeMx) // debug { MoleculeMx cs = fieldValue as MoleculeMx; MoleculeFormat csType = cs.PrimaryFormat; string csValue = cs.PrimaryValue; int csLen = cs.PrimaryValue.Length; string molfile = cs.GetMolfileString(); molfile = molfile; } try { // If already formatted use existing formatting info ffi = null; if (fieldValue is MobiusDataType) { mdt = (MobiusDataType)fieldValue; if (mdt.FormattedBitmap != null) { ffi = new FormattedFieldInfo(); ffi.FormattedBitmap = mdt.FormattedBitmap; } else if (mdt.FormattedText != null) { ffi = new FormattedFieldInfo(); ffi.FormattedText = mdt.FormattedText; } if (ffi != null) // if formatted then copy other format attributes as well { ffi.BackColor = mdt.BackColor; ffi.ForeColor = mdt.ForeColor; ffi.Hyperlink = mdt.Hyperlink; } } // If not formatted then format if (ffi == null) // need to format? { // Format non-image field (including structures) if (ci.Mc.DataType != MetaColumnType.Image) // format other than image immediately { //if (ci.Mc.DataType == MetaColumnType.Structure) // debug //{ // DebugLog.Message(fieldValue.ToString()); // UIMisc.Beep(); //} ffi = fmtr.FormatField(ci.Rt, ci.TableIndex, ci.Rfld, ci.FieldIndex, dr, e.ListSourceRowIndex, fieldValue, ci.DataRowIndex, false); FormatFieldCalls++; if (ci.Mc.DataType == MetaColumnType.Structure) { FormatStructureFieldCalls++; } StoreFormattingInformationInMdt(ffi, fieldValue, dr, ci, mdt); formatted = true; } // Image: start asynch call to get image in background as necessary since it is too slow to wait for it here else { if (fieldValue is ImageMx) { imageMx = fieldValue as ImageMx; } else { imageMx = new ImageMx(); if (fieldValue != null) { if (fieldValue is MobiusDataType) { imageMx.DbLink = (fieldValue as MobiusDataType).DbLink; } else { imageMx.DbLink = fieldValue.ToString(); // store field value as dblink } } dr.ItemArrayRef[ci.DataColIndex] = imageMx; // store new image object without firing event } mdt = imageMx; // copy image object to general MobiusDataType ffi = new FormattedFieldInfo(); if (imageMx.FormattedBitmap != null) // already have bitmap? { ffi.FormattedBitmap = imageMx.FormattedBitmap; } else if (imageMx.Value != null) // have the bitmap, just need to scale it { int fieldWidth = ci.Rfld.FieldWidth; // current field width in milliinches int desiredWidth = (int)((fieldWidth / 1000.0) * GraphicsMx.LogicalPixelsX * 1.0); // width in pixels imageMx.FormattedBitmap = BitmapUtil.ScaleBitmap(imageMx.Value, desiredWidth); ffi.FormattedBitmap = imageMx.FormattedBitmap; } else if (imageMx.IsRetrievingValue) // already retrieving? { ffi.FormattedBitmap = (Bitmap)RetrievingImageMsg.Image; // put up the processing image } else if (SS.I.AsyncImageRetrieval) // start async image retrieval { FormatImageFieldCalls++; GetImageBitmapAsync(ci, dr, e.ListSourceRowIndex, fieldValue, imageMx, callId); ffi.FormattedBitmap = (Bitmap)RetrievingImageMsg.Image; // put up the processing image } else // do synchronous image retrieval { GetImageBitmap(ci, dr, e.ListSourceRowIndex, fieldValue, imageMx, callId); ffi.FormattedBitmap = imageMx.FormattedBitmap; formatted = true; } } } //if (ci.Mc.DataType == MetaColumnType.CompoundId && String.IsNullOrEmpty(fmtdFld.Hyperlink)) ci = ci; // debug //if (mdt is CompoundId) mdt = mdt; // debug if (e.Column.ColumnEdit is RepositoryItemPictureEdit) { if (ffi != null && ffi.FormattedBitmap != null) { e.Value = ffi.FormattedBitmap; } else { e.Value = new Bitmap(1, 1); // avoid no-image data message } //ffi.FormattedBitmap.Save(@"c:\download\test.bmp"); // debug } else { e.Value = ffi.FormattedText; // non-picture column } if (ci.DataRowIndex == DataTable.Rows.Count - 1 && // if at end of DataTable && more rows available, request them !Dtm.RowRetrievalComplete) { //Progress.Show("Retrieving data..."); // put up progress dialog if not already up //if (WaitForMoreDataStartTime.Equals(DateTime.MinValue)) // say we've started waiting for data //{ // WaitForMoreDataStartTime = DateTime.Now; // ClientLog.Message("Set WaitForMoreDataStartTime: " + WaitForMoreDataStartTime.ToLongTimeString()); //} if (Dtm.RowRetrievalState == RowRetrievalState.Paused) { Dtm.StartRowRetrieval(); // .ReadNextRowsFromQueryEngine(); // restart retrieval } } else if (Lex.StartsWith(Progress.GetCaption(), "Retrieving data...") || Lex.IsUndefined(Progress.GetCaption())) { // hide any "Retrieving data..." message Progress.Hide(); //SystemUtil.Beep(); } Grid.LastRowRendered = e.ListSourceRowIndex; if (DebugDetails) { debugMsg = "Grid.GetData: " + callId + ", e.Row = " + e.ListSourceRowIndex + ", e.Col = " + e.Column.AbsoluteIndex + ", Formatted = " + (formatted ? "T" : "F") + ", Time(ms) = " + TimeOfDay.Delta(t0) + ", ColLabel = " + ci.Qc.ActiveLabel; debugMsg += ", FieldValue = "; if (fieldValue != null) { debugMsg += fieldValue.ToString(); } debugMsg += ", e.Value = "; if (e.Value != null) { debugMsg += e.Value.ToString(); } else { debugMsg += "null"; } ClientLog.Message(debugMsg); } // TODO: This does a some unnecessary hides which cause flashing of the window frame // This happens when we are not at the end of the DataTable but don't know if any additional requests // for rendering will occur. May be better to move this to DataTableManger when we detect // that we have retrieved a row that is below the level of those displayed in the grid or all rows have been retrieved. // Also maybe in MoleculeGridControl.RetrievalMonitorTimer_Tick } catch (Exception ex) { if (e.Column.ColumnEdit is RepositoryItemPictureEdit) { e.Value = new Bitmap(1, 1); // avoid no-image data message } else { e.Value = ex.Message; } string msg = "ColumnView_CustomUnboundColumnData Exception"; if (ci.Rfld != null) { msg += ", MetaColumn: " + ci.Rfld.MetaColumn.MetaTable.Name + "." + ci.Rfld.MetaColumn.Name; } msg += ", DataColIndex: " + ci.DataColIndex + ", DataRowIndex: " + ci.DataRowIndex; if (fieldValue != null) { msg += ", Value: " + fieldValue.ToString(); } ClientLog.Message(msg); } // t0 = TimeOfDay.Milliseconds() - t0; // ClientLog.Message("CustomUnboundColumnData event time: " + t0); }
/// <summary> /// Call any data changed event handlers for both the IList and DataTable interfaces /// </summary> /// <param name="listChangedType"></param> /// <param name="row"></param> internal void CallDataChangedEventHandlers( ListChangedType listChangedType, DataRowMx row) { CallDataChangedEventHandlers(listChangedType, row, -1); }
/// <summary> /// Update the match counts panel and structure view based on a set of structures and filter values /// </summary> /// <param name="excludeCurrentHitList"></param> /// <param name="rssrs"></param> public void DisplayRelatedStructures( List <StructSearchMatch> fml) { MoleculeMx cs; if (fml == null || fml.Count == 0) { DisplayEmptyStructureGrid(); return; } if (StructureDisplayQuery == null) { BuildStructureDisplayQuery(); // initial setup } Query q = StructureDisplayQuery; QueryTable qt = q.Tables[0]; DataTableMx dt = Qm.DataTable; MoleculeGridControl grid = Qm.MoleculeGrid; grid.BeginUpdate(); dt.Clear(); // filter table HashSet <string> cidSet = new HashSet <string>(); for (int mi = 0; mi < fml.Count; mi++) // build and add the rows to the datatable of structures { StructSearchMatch ssm = fml[mi]; DataRowMx dr = dt.NewRow(); dr[qt.Alias + ".CompoundId"] = ssm.SrcCid; cs = new MoleculeMx(ssm.MolStringFormat, ssm.MolString); if (Lex.IsDefined(ssm.SrcCid)) { cs.SetMolComments("CorpId=" + ssm.SrcCid); // Attach CorpId to Molfile so it will be rendered correctly } if (ssm.SearchType == StructureSearchType.SmallWorld && Lex.IsDefined(ssm.GraphicsString)) { cs.SvgString = ssm.GraphicsString; } dr[qt.Alias + ".Structure"] = cs; dr[qt.Alias + ".MatchType"] = ssm.SearchTypeName; dr[qt.Alias + ".MatchScore"] = ssm.MatchScore; dr[qt.Alias + ".Database"] = ssm.SrcName; dt.Rows.Add(dr); cidSet.Add(ssm.SrcCid); } Qm.DataTableManager.InitializeRowAttributes(); string title = "Related Structures - Matches: " + fml.Count + ", Compound Ids: " + cidSet.Count; Qm.MoleculeGrid.SetTableHeaderCaption(0, title); if (!RSC.MoleculeGridPageControl.Visible) { RSC.MoleculeGridPageControl.Visible = true; } grid.EndUpdate(); ToolHelper.RefreshDataDisplay(Qm); return; }
/// <summary> /// Build click function and field value text string for output /// ClickFunction arguments may be defined in the clickfunction definition including col values /// indicated by fieldName.Value in the metacolumn clickfunction definition. /// If no args are defined in the clickfunction definition then a field value /// argument will be added by default, the keyValue if [keyvalue] or /// [rowcol] as a grid row and column to be returned if these appear in the /// ClickFunction definition. /// </summary> /// <param name="rf">Results field to display link for</param> /// <param name="vo">Vo contain tuple values</param> /// <param name="displayValue">Formatted display value for field</param> /// <returns></returns> public static string BuildClickFunctionText( ResultsField rf, DataRowMx dr, int dri, string displayValue) { ResultsTable rt; MetaColumn mc, mc2; MetaTable mt; string arg, arg2, argsString; int ai, rfi, voi; if (rf == null || dr == null || dri < 0) { return(""); } rt = rf.ResultsTable; mc = rf.MetaColumn; mt = mc.MetaTable; object[] vo = dr.ItemArray; if (String.IsNullOrEmpty(mc.ClickFunction)) { return(""); } List <string> args = Lex.ParseAllExcludingDelimiters(mc.ClickFunction, "( , )", false); string funcName = args[0]; // click function name int fieldRefs = 0; for (ai = 1; ai < args.Count; ai++) { // see how many mcName.Value references there are arg = args[ai]; string suffix = ".Value"; if (!Lex.EndsWith(arg, suffix)) { continue; } arg = arg.Substring(0, arg.Length - suffix.Length); if (mt.GetMetaColumnByName(arg) != null) { fieldRefs++; } } if (fieldRefs == 0) // if no field references add either the field value, key value or grid row and column { if (Lex.Eq(funcName, "RunHtmlQuery") || Lex.Eq(funcName, "RunGridQuery") || Lex.Eq(funcName, "DisplayWebPage")) // fixups for old functions { args.Add(Lex.AddSingleQuotes(mt.Name)); // add metatable name args.Add(Lex.AddSingleQuotes(mc.Name)); // add metacolumn name } if (Lex.Contains(mc.ClickFunction, "[TableColumnValue]")) // convert to metatable, metacolumns, &value refDataTable row & col { args.RemoveAt(1); // remove [TableColumnValue] arg args.Add(Lex.AddSingleQuotes(mt.Name)); args.Add(Lex.AddSingleQuotes(mc.Name)); args.Add(mc.Name + ".Value"); } else if (Lex.Contains(mc.ClickFunction, "[keyvalue]")) { args.Add(mt.KeyMetaColumn.Name + ".value"); // pass key value rather than this col value } else { args.Add(mc.Name + ".value"); // pass column value } } argsString = ""; for (ai = 1; ai < args.Count; ai++) { arg = args[ai]; string suffix = ".Value"; if (!arg.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) { continue; } arg2 = arg.Substring(0, arg.Length - suffix.Length); mc2 = mt.GetMetaColumnByName(arg2); if (mc2 == null) { continue; // assume unquoted string constant & pass as is } else if (mc2.IsKey && rt.Fields[0].MetaColumn.Name != mc2.Name) { // see if undisplayed key value voi = rt.Fields[0].VoPosition - 1; // position in vo } else // find the field name in the list of report fields { for (rfi = 0; rfi < rt.Fields.Count; rfi++) { if (Lex.Eq(mc2.Name, rt.Fields[rfi].MetaColumn.Name)) { break; } } if (rfi >= rt.Fields.Count) { throw new Exception("Column name not selected in query: " + mc2.Name); } voi = rt.Fields[rfi].VoPosition; } if (vo[voi] == null) { args[ai] = ""; } else { arg = vo[voi].ToString(); if (vo[voi] is MobiusDataType) { // use dblink if defined MobiusDataType mdt = vo[voi] as MobiusDataType; if (!String.IsNullOrEmpty(mdt.DbLink)) { arg = mdt.DbLink; } } args[ai] = arg; } } for (ai = 1; ai < args.Count; ai++) { arg = args[ai]; if (!Lex.IsDouble(arg) && !arg.StartsWith("'") && !arg.StartsWith("[")) // quote if string { arg = Lex.AddSingleQuotes(arg); } if (argsString != "") { argsString += ","; } argsString += arg; } string txt = // build full string including link & display value "<a href=\"http:////Mobius/command?ClickFunction " + funcName + "(" + argsString + ")\">" + displayValue + "</a>"; return(txt); }
/// <summary> /// Store selected formatting information for possible use later needed later /// </summary> /// <param name="ffi"></param> /// <param name="fieldValue"></param> /// <param name="dr"></param> /// <param name="ci"></param> /// <param name="mdt"></param> void StoreFormattingInformationInMdt(FormattedFieldInfo ffi, object fieldValue, DataRowMx dr, CellInfo ci, MobiusDataType mdt) { bool hyperLinked = !String.IsNullOrEmpty(ffi.Hyperlink); if (ffi.ForeColor != Color.Black || ffi.BackColor != Color.Empty || hyperLinked) { // store any formatting info in a MDT so that it's available for the later display RowCellStyle event if (mdt == null && !NullValue.IsNull(fieldValue)) // need to create MDT? { //if (ci.Mc.DataType == MetaColumnType.Structure) ci = ci; // debug mdt = MobiusDataType.New(ci.Mc.DataType, fieldValue); dr.ItemArrayRef[ci.DataColIndex] = mdt; // store new value without firing event } if (mdt.BackColor != ffi.BackColor) { mdt.BackColor = ffi.BackColor; // set in DataTable only if changed to avoid repaints } if (mdt.ForeColor != ffi.ForeColor) { mdt.ForeColor = ffi.ForeColor; } if (mdt.Hyperlink != ffi.Hyperlink) { mdt.Hyperlink = ffi.Hyperlink; } if (mdt.Hyperlinked != hyperLinked) { mdt.Hyperlinked = hyperLinked; } if (ffi.FormattedBitmap != null) { mdt.FormattedBitmap = ffi.FormattedBitmap; } if (ffi.FormattedText != null) { mdt.FormattedText = ffi.FormattedText; } } }
/// <summary> /// Scale and translate structure and format into buffer /// </summary> /// <param name="mol">The structure</param> /// <param name="cellStyle">Style/conditional formatting to apply to cell</param> /// <param name="commandChar">Command character to use in buffer</param> /// <param name="x">Coordinate of left side of structure</param> /// <param name="width">Width of molecule box in milliinches</param> /// <param name="r">Row in buffer to put on. If less than 0 then return formatted data</param> /// <param name="heightInLines">number of lines used</param> public FormattedFieldInfo FormatStructure( MoleculeMx mol, CellStyleMx cellStyle, char commandChar, int x, int width, int r, ResultsField rfld = null, DataRowMx dataRow = null) { Rectangle destRect, boundingRect; int height; // formatted height in milliinches bool markBoundaries; int fixedHeight; Bitmap bm; Font font; string txt, molfile, molString = "", svg, cid = null; int translateType, desiredBondLength = 100; int pixWidth = 0, pixHeight = 0; bool debug = DataTableManager.DebugDetails; if (debug) { DebugLog.Message("=============================== FormattingStructure ==============================="); } PerformanceTimer pt = PT.Start("FormatStructure"); Stopwatch swTotal = Stopwatch.StartNew(); Stopwatch sw = Stopwatch.StartNew(); try { MoleculeFormat initialCsType = mol.PrimaryFormat; string initialCsValue = mol.PrimaryValue; QueryColumn qc = (rfld != null) ? rfld.QueryColumn : null; FormattedFieldInfo ffi = new FormattedFieldInfo(); if (dataRow != null) // get any cid in row { int ki = DataTableManager.DefaultKeyValueVoPos; if (ki < dataRow.Length) { cid = dataRow[ki] as string; } } //DebugLog.Message("FormatStructure " + cid); //if (!Rf.Grid) x = x; // debug /////////////////////////////////// // Highlight structure /////////////////////////////////// if (StructureHighlightPssc != null) { ParsedStructureCriteria pssc = StructureHighlightPssc; // Hilight substructure search match if (pssc.SearchType == StructureSearchType.Substructure || // regular SSS pssc.SearchTypeUnion == StructureSearchType.Substructure) // handles related search for just SSS to get hilighting { if (HighlightStructureMatches) { try { mol = StrMatcher.HighlightMatchingSubstructure(mol); if (DebugMx.False) // debug { //string highlightChildren = mol.MolLib.HighlightChildren; //Color highlightColor = mol.MolLib.HighlightColor; if (debug) { DebugLog.StopwatchMessage("tHilight", sw); } } } catch (Exception ex) { ex = ex; } } if (AlignStructureToQuery) { try { mol = StrMatcher.AlignToMatchingSubstructure(mol); if (debug) { DebugLog.StopwatchMessage("tOrient", sw); } } catch (Exception ex) { ex = ex; } } } // Hilight SmallWorld structure match else if (pssc.SearchType == StructureSearchType.SmallWorld) // Hilight SmallWorld structure search results { if (SmallWorldDepictions == null) { SmallWorldDepictions = new SmallWorldDepictions(); } SmallWorldPredefinedParameters swp = pssc.SmallWorldParameters; //DebugLog.Message("Depict " + cid + ", Hilight " + swp.Highlight + ", Align " + swp.Align); // + "\r\n" + new StackTrace(true)); if ((swp.Highlight || swp.Align) & Lex.IsDefined(cid)) // call depiction for these { svg = SmallWorldDepictions.GetDepiction(cid, swp.Highlight, swp.Align); if (Lex.IsDefined(svg)) // have depiction? { { pixWidth = MoleculeMx.MilliinchesToPixels(width); bm = SvgUtil.GetBitmapFromSvgXml(svg, pixWidth); ffi.FormattedBitmap = mol.FormattedBitmap = bm; // store in formatting info and chem structure return(ffi); } } else if (svg == null) // start retrieval of this decpiction type & fall through to get default structure initially { SmallWorldDepictions.StartDepictionRetrieval(Qm, StructureHighlightQc, swp.Highlight, swp.Align); } else { } // tried to get it but failed, fall through to get basic structure } } else if (mol.AltFormDefined("Svg")) // svg form exist (e.g. SmallWorld or "related" structure search)? { svg = mol.SvgString; if (Lex.IsDefined(svg)) { pixWidth = MoleculeMx.MilliinchesToPixels(width); bm = SvgUtil.GetBitmapFromSvgXml(svg, pixWidth); ffi.FormattedBitmap = mol.FormattedBitmap = bm; // store in formatting info and chem structure return(ffi); } } } /////////////////////////////////// // Handle each output device /////////////////////////////////// ffi.HeightInLines = 1; // min of 1 line if (Rf.SdFile) { FormatSdfileStructure(mol); return(null); } int pageHeight = 11000; if (Rf.PageMargins != null) { pageHeight = Rf.PageMargins.Top + Rf.PageHeight + Rf.PageMargins.Bottom; } if (Rf.Excel || Rf.Word) { translateType = 2; } else { translateType = 0; } if (!Rf.FixedHeightStructures) { fixedHeight = 0; // not fixed height } else if (Rf.Excel || Rf.Word) { fixedHeight = 1; // always fixed height } else { fixedHeight = 2; // fixed height unless need to expand } if (Rf.Word && Rf.FixedHeightStructures) { markBoundaries = true; } else { markBoundaries = false; } destRect = new Rectangle(0, 0, width, width * 4 / 5); // default dest rect /////////////////////////////////////////////////////////////////////////// // Tempory fake generation of HELM & associatedimage for biopolymer testing /////////////////////////////////////////////////////////////////////////// //if (MoleculeMx.HelmEnabled == DebugMx.False) // artificially generate helm molecules // MoleculeMx.SetMoleculeToTestHelmString(mol.GetCorpId().ToString(), mol); /////////////////////////////////////////////////////////////////////////// // End of tempory fake generation of HELM & associatedimage for biopolymer testing /////////////////////////////////////////////////////////////////////////// bool fitStructure = true; if (mol.IsChemStructureFormat) { if (Rf.Grid) // special scale for grid { double scale = (float)width / MoleculeMx.StandardBoxWidth; desiredBondLength = mol.CdkMol.AdjustBondLengthToValidRange((int)(MoleculeMx.StandardBondLength * scale)); //desiredBondLength = (int)(ChemicalStructure.StandardBondLength * (Rf.PageScale / 100.0)); desiredBondLength = (int)(desiredBondLength * 90.0 / 100.0); // scale down a bit for grid if (debug) { DebugLog.StopwatchMessage("tAdjustBondLength1", sw); } } else // set desired bond length based on page scaling { float scale = (float)width / MoleculeMx.StandardBoxWidth; desiredBondLength = mol.CdkMol.AdjustBondLengthToValidRange((int)(MoleculeMx.StandardBondLength * scale)); //desiredBondLength = (int)(ChemicalStructure.StandardBondLength * (Rf.PageScale / 100.0)); if (debug) { DebugLog.StopwatchMessage("tAdjustBondLength2", sw); } } if (desiredBondLength < 1) { desiredBondLength = 1; } if (debug) { DebugLog.StopwatchMessage("tBeforeFit", sw); } if (fitStructure) { mol.CdkMol.FitStructureIntoRectangle // scale and translate structure into supplied rectangle. (ref destRect, desiredBondLength, translateType, fixedHeight, markBoundaries, pageHeight, out boundingRect); } if (debug) { DebugLog.StopwatchMessage("tFitStructure", sw); } ffi.HeightInLines = (int)(destRect.Height / Rf.LineHeight + 1); // lines needed } else if (mol.IsBiopolymerFormat) { if (mol.PrimaryFormat == MoleculeFormat.Helm && Rf.Excel) { svg = HelmControl.GetSvg(mol.HelmString); float inchWidth = width / 1000.0f; // convert width milliinches to inches Svg.SvgDocument svgDoc = SvgUtil.AdjustSvgDocumentToFitContent(svg, inchWidth, Svg.SvgUnitType.Inch); RectangleF svgbb = svgDoc.Bounds; float ar = svgbb.Width / svgbb.Height; // aspect ratio of svg bounding box height = (int)(width / ar); // height in milliinches ffi.HeightInLines = (int)(height / Rf.LineHeight) + 1; // lines needed destRect = new Rectangle(0, 0, width, height); } } ////////////////////////// /// Output to Grid ////////////////////////// if (Rf.Grid) { pixWidth = MoleculeMx.MilliinchesToPixels(destRect.Width); pixHeight = MoleculeMx.MilliinchesToPixels(destRect.Height); if (cellStyle == null) { if (Qm == null || Qm.MoleculeGrid == null) { font = new Font("Tahoma", 8.25f); } else { font = new Font(Qm.MoleculeGrid.Font, FontStyle.Underline); } cellStyle = new CellStyleMx(font, Color.Blue, Color.Empty); } if (mol.IsChemStructureFormat) // molfile type molecule { if (debug) { DebugLog.StopwatchMessage("tBeforeGetDisplayPreferences", sw); } DisplayPreferences dp = mol.GetDisplayPreferences(); if (debug) { DebugLog.StopwatchMessage("tGetDisplayPreferences", sw); } //desiredBondLength = mol.CdkMol.AdjustBondLengthToValidRange(desiredBondLength); // be sure bond len within allowed range //if (debug) DebugLog.StopwatchMessage("tAdjustBondLengthToValidRange", sw); //dp.StandardBondLength = MoleculeMx.MilliinchesToDecipoints(desiredBondLength); bm = mol.CdkMol.GetFixedHeightMoleculeBitmap(pixWidth, pixHeight, dp, cellStyle, mol.Caption); if (debug) { DebugLog.StopwatchMessage("tGetBitmap", sw); } } else if (mol.IsBiopolymerFormat) // Output HELM image for biopolymer { pixWidth = MoleculeMx.MilliinchesToPixels(width); bm = HelmConverter.HelmToBitmap(mol, pixWidth); } else { bm = new Bitmap(1, 1); } ffi.FormattedBitmap = mol.FormattedBitmap = bm; // store in formatting & structure ffi.FormattedText = "Formatted"; // indicate formatted (could save structure string but not needed and avoids possible conversion overhead) return(ffi); } ////////////////////////// /// Output to Html ////////////////////////// else if (Rf.Html) { if (r >= 0) { AssureTbFree(0, r + ffi.HeightInLines - 1); } if (mol.IsChemStructureFormat) { FormatChemStructureHtml(mol, destRect, width, r); } else if (mol.IsBiopolymerFormat) { FormatBiopolymerStructureHtml(mol, destRect, width, r); } if (debug) { DebugLog.StopwatchMessage("tFormatHtmlStructure", sw); } ffi.FormattedBitmap = mol.FormattedBitmap; ffi.FormattedText = mol.FormattedText; return(ffi); } ///////////////////////////////////////////////////////////////// /// Other format, store Smiles or Helm & any cellStyle in buffer ///////////////////////////////////////////////////////////////// else { if (mol.IsChemStructureFormat) { if (Rf.ExportStructureFormat == ExportStructureFormat.Smiles) { molString = mol.GetSmilesString(); } else { molString = mol.GetChimeString(); // use Chime if not smiles } } else if (mol.IsBiopolymerFormat) { molString = mol.PrimaryValue; // usually Helm but could be sequence } txt = String.Format("{0} {1} {2} {3} {4} {5} {6}", x, width, destRect.Left, destRect.Top, destRect.Right, destRect.Bottom, molString); if (cellStyle != null) // apply style to cell? { txt += " <CellStyle " + cellStyle.Serialize() + ">"; } txt = commandChar + " " + txt + "\t"; if (r >= 0) { AssureTbFree(0, r + ffi.HeightInLines - 1); Tb.Lines[r] += txt; // put in buffer } else { return(new FormattedFieldInfo(txt)); // just return formatting } } return(null); } catch (Exception ex) { DebugLog.Message(DebugLog.FormatExceptionMessage(ex)); return(null); } finally { pt.Update(); int formatCount = pt.Count; //ClientLog.Message(pt.ToString() + ", " + cs.GetMolHeader()[2]); // + ", " + new StackTrace(true)); if (debug) { DebugLog.StopwatchMessage("tTotalTime", swTotal); } } }
/// <summary> /// Build tooltip for data row /// </summary> /// <param name="dri">Data row index</param> /// <returns></returns> internal SuperToolTip BuildDataRowTooltip( TooltipDimensionDef ttDim, int dri) { ColumnMapMsx cm; QueryTable qt; QueryColumn qc; MetaTable mt; MetaColumn mc; int i1, i2; if (BaseQuery == null || BaseQuery.Tables.Count == 0 || Dtm == null) { return(null); } qt = BaseQuery.Tables[0]; SuperToolTip s = new SuperToolTip(); s.MaxWidth = 200; s.AllowHtmlText = DefaultBoolean.True; ToolTipItem i = new ToolTipItem(); i.AllowHtmlText = DefaultBoolean.True; i.Appearance.TextOptions.WordWrap = WordWrap.Wrap; ColumnMapCollection cml2 = new ColumnMapCollection(); // list of fields we'll actually display int strPos = -1; ColumnMapCollection cml = ttDim.Fields; if (cml.Count == 0) { return(s); } for (i1 = 0; i1 < cml.Count; i1++) { cm = cml[i1]; qc = cm.QueryColumn; if (qc == null || !cm.Selected) { continue; } //if (qc.IsKey) continue; if (qc.MetaColumn.DataType == MetaColumnType.Structure) { strPos = i1; } for (i2 = 0; i2 < cml2.Count; i2++) // see if already have the column { if (qc == cml2[i2].QueryColumn) { break; } } if (i2 < cml2.Count) { continue; } cml2.Add(cm); } if (cml2.Count == 0) { return(null); // no fields } if (strPos < 0 && ttDim.IncludeStructure) { // include str if requested & not already included qc = qt.FirstStructureQueryColumn; strPos = cml2.Count; // put str at end //strPos = keyPos + 1; // place str after key if (qc != null && qc.Selected) // regular selected Qc? { cml2.ColumnMapList.Insert(strPos, ColumnMapMsx.BuildFromQueryColumn(qc)); } else // look in root table for a structure { mt = qt.MetaTable.Root; if (mt.FirstStructureMetaColumn != null) { qt = new QueryTable(mt); qc = new QueryColumn(); // add qc with no vo pos as indicator that must be selected qc.MetaColumn = mt.FirstStructureMetaColumn; qc.Selected = true; qt.AddQueryColumn(qc); cml2.ColumnMapList.Insert(strPos, ColumnMapMsx.BuildFromQueryColumn(qc)); } } } string keyVal = ""; foreach (ColumnMapMsx fli0 in cml2.ColumnMapList) // format each field { qc = fli0.QueryColumn; mc = qc.MetaColumn; i.Text += "<b>"; // build label if (!Lex.IsNullOrEmpty(fli0.ParameterName)) { i.Text += fli0.ParameterName; } else { i.Text += fli0.QueryColumn.ActiveLabel; } i.Text += ": </b>"; if (qc.VoPosition >= 0) { int ti = qc.QueryTable.TableIndex; int dri2 = Dtm.AdjustDataRowToCurrentDataForTable(dri, ti, true); DataRowMx dr = Qm.DataTable.Rows[dri2]; if (dr == null) { continue; } ResultsTable rt = Rf.Tables[ti]; object fieldValue = dr[qc.VoPosition]; if (!NullValue.IsNull(fieldValue)) { if (qc.IsKey) { keyVal = fieldValue.ToString(); } MobiusDataType mdt = MobiusDataType.ConvertToMobiusDataType(qc.MetaColumn.DataType, fieldValue); FormattedFieldInfo ffi = Qm.ResultsFormatter.FormatField(qc, mdt); if (mc.DataType != MetaColumnType.Structure) { i.Text += ffi.FormattedText; i.Text += "<br>"; } else { i = ToolTipUtil.AppendBitmapToToolTip(s, i, ffi.FormattedBitmap); } } else { i.Text += "<br>"; // no data } } else if (!Lex.IsNullOrEmpty(keyVal)) // select structure from db (may already have) { MoleculeMx cs = MoleculeUtil.SelectMoleculeForCid(keyVal, qc.MetaColumn.MetaTable); if (cs != null) { int width = ResultsFormatFactory.QcWidthInCharsToDisplayColWidthInMilliinches(mc.Width, ResultsFormat); FormattedFieldInfo ffi = Qm.ResultsFormatter.FormatStructure(cs, new CellStyleMx(), 's', 0, width, -1); i = ToolTipUtil.AppendBitmapToToolTip(s, i, ffi.FormattedBitmap); } } } if (i.Text.Length > 0) { s.Items.Add(i); } if (s.Items.Count == 0) { // show something by default i = new ToolTipItem(); i.Text = "No fields selected"; i.LeftIndent = 6; i.Appearance.TextOptions.WordWrap = WordWrap.Wrap; s.Items.Add(i); } //ToolTipTitleItem ti = new ToolTipTitleItem(); //ti.Text = "Dude"; //s.Items.Add(ti); //ToolTipItem i = new ToolTipItem(); //i.Text = "Subtext that is fairly long longer longest"; //i.LeftIndent = 6; //i.Appearance.TextOptions.WordWrap = WordWrap.Wrap; //s.Items.Add(i); //i = new ToolTipItem(); //Image img = Bitmap.FromFile(@"C:\Mobius_OpenSource\Mobius-3.0\ClientComponents\Resources\Mobius76x76DkBlueBack.bmp"); //i.Image = img; //s.Items.Add(i); //ToolTipSeparatorItem si = new ToolTipSeparatorItem(); return(s); //ChartPanel.ToolTipController.ToolTipLocation = ToolTipLocation.TopCenter; //ChartPanel.ToolTipController.AllowHtmlText = true; //string s = point.SeriesPointID.ToString(); //s = "This <b>SuperToolTip</b> supports <i>HTML formatting</i>"; }
/// <summary> /// Flatten dataset row & add to list value objects /// </summary> /// <param name="dr"></param> /// <param name="rf"></param> /// <returns></returns> public static List <object[]> FlattenDataRow( DataRowMx dr, ResultsFormat rf) { ResultsTable rt; QueryTable qt; QueryColumn qc; DataSet ds; DataTableMx dt; DataRow[] dRows = null; DataRelation dRel; object[] vo = null; int ti, ri, ci; Query q = rf.Query; ds = dr.Table.DataSet; // assoc data set List <object[]> voBuffer = new List <object[]>(); object keyValue = dr[0]; // assume key value is in 1st position if (keyValue is CompoundId) { keyValue = ((CompoundId)keyValue).Value; // get cid as string } for (ti = 0; ti < q.Tables.Count; ti++) // process each table { rt = rf.Tables[ti]; qt = q.Tables[ti]; dt = ds.Tables[ti]; if (ti == 0) { dRows = new DataRow[1]; dRows[0] = dr; } else { dRel = ds.Relations[ti - 1]; // assume relations in same order as tables dt = dRel.ChildTable; dRows = dr.GetChildRows(dRel); } for (ri = 0; ri < dRows.Length; ri++) { dr = dRows[ri]; if (ri >= voBuffer.Count) { vo = new Object[rf.VoLength]; // vo to be filled vo[0] = keyValue; // copy key to common first element voBuffer.Add(vo); // add to array of flattened tuples } for (ci = 0; ci < qt.QueryColumns.Count; ci++) { qc = qt.QueryColumns[ci]; if (!qc.Selected) { continue; } object value = dr[ci]; if (value is DBNull) { value = null; } else if (value is CompoundId) { value = ((CompoundId)value).Value; // get cid as string } // else if (value is ChemicalStructure) value = ((ChemicalStructure)value).Value; vo[qc.VoPosition] = value; } } } // end for result merge return(voBuffer); }
/// <summary> /// Attempt to read existing results file into the query DataTable /// </summary> /// <param name="qm"></param> public void ReadBinaryResultsFile(string fileName) { QueryTable qt; QueryColumn qc; BinaryReader br = null; Stopwatch sw = Stopwatch.StartNew(); try { bool saveHandlersEnabled = Qm.DataTable.EnableDataChangedEventHandlers(false); // disable for faster load bool saveUpdateMaxRowsPerKey = UpdateMaxRowsPerKeyEnabled; UpdateMaxRowsPerKeyEnabled = false; // disable for faster load int id = Query.UserObject.Id; if (id <= 0) { throw new Exception("Query not saved"); } if (DataTableMx == null || DataTableMx.Columns.Count == 0) { throw new Exception("DataTable not defined"); } br = BinaryFile.OpenReader(fileName); string sq = br.ReadString(); Query q0 = Query.Deserialize(sq); // deserialize the saved query QueryManager qm0 = new QueryManager(); qm0.LinkMember(q0); ResultsFormat rf0 = new ResultsFormat(qm0, OutputDest.WinForms); ResultsFormatFactory rff0 = new ResultsFormatFactory(qm0, OutputDest.WinForms); rff0.Build(); // build format with vo positions // The cached query cols should match those of the current query: however, // we'll create a mapping just in case they don't int voArrayLen0 = br.ReadInt32(); // cached vo array len int voArrayLen = DataTableMx.Columns.Count - KeyValueVoPos; // current query vo array len List <int> q0VoMap = new List <int>(); // vo position in cached query data List <int> qVoMap = new List <int>(); // vo position in current version of query q0VoMap.Add(0); // first position is the common key value qVoMap.Add(0); foreach (QueryTable qt0 in q0.Tables) // scan each table in cached data { foreach (QueryColumn qc0 in qt0.QueryColumns) // and each column { if (qc0.VoPosition < 0) { continue; // skip if not mapped to the vo in cached data } int q0VoPos = qc0.VoPosition - KeyValueVoPos; // where it is in cache int qvoPos = -1; // where it will go qt = Query.GetTableByName(qt0.MetaTable.Name); if (qt != null) { qc = qt.GetQueryColumnByName(qc0.MetaColumn.Name); if (qc != null) { qvoPos = qc.VoPosition - KeyValueVoPos; } } q0VoMap.Add(q0VoPos); // where it is in saved data qVoMap.Add(qvoPos); // where it will go (not including attributes & check cols) } } if (q0VoMap.Count != voArrayLen0) { throw new Exception("Cached Vo length doesn't match list of selected columns"); } DataTableMx.Clear(); // clear the rows CidList cidList = new CidList(); object[] voa = new object[voArrayLen]; // array to fill while (!BinaryFile.ReaderEof(br)) // process each row { for (int mi = 0; mi < q0VoMap.Count; mi++) // each col { object o = VoArray.ReadBinaryItem(br); if (mi == 0 && o != null) // add to key list if key { cidList.Add(o.ToString(), false); } if (qVoMap[mi] >= 0) // save in new buf if mapped { voa[qVoMap[mi]] = o; } } DataRowMx dr = AddDataRow(voa); } br.Close(); Qm.DataTable.EnableDataChangedEventHandlers(saveHandlersEnabled); UpdateMaxRowsPerKeyEnabled = saveUpdateMaxRowsPerKey; InitializeRowAttributes(false); ResultsKeys = cidList.ToStringList(); // include keys in DTM as well double ms = sw.Elapsed.TotalMilliseconds; return; } catch (Exception ex) { if (br != null) { br.Close(); } throw new Exception(ex.Message, ex); } }