static void pwrsrv_WriteAttribute( rpvd_sMsgWriteAttribute *msg) { rpvd_sMsgAny rmsg; pwr_tAName name; pwr_tUInt32 asize, aoffs, aelem; pwr_tTypeId atid; pwr_tStatus sts; rmsg.Type = rpvd_eMsg_Status; rmsg.Id = msg->Id; sts = gdh_ObjidToName( msg->Oid, name, sizeof(name), cdh_mName_volumeStrict); if ( EVEN(sts)) { rmsg.Status = sts; udp_Send( (char *)&rmsg, sizeof(rmsg)); return; } strcat( name, "."); strcat( name, msg->Attribute); sts = gdh_GetAttributeCharacteristics( name, &atid, &asize, &aoffs, &aelem); if ( EVEN(sts)) { rmsg.Status = sts; udp_Send( (char *)&rmsg, sizeof(rmsg)); return; } sts = gdh_SetObjectInfo( name, &msg->Value, msg->Size); rmsg.Status = sts; udp_Send( (char *)&rmsg, sizeof(rmsg)); }
int print_attribute( pwr_tAttrRef *arp, pwr_tClassId classid, char *object_p, char *attributename, int array_element, int index, FILE *fp) { pwr_tTypeId tid; pwr_tUInt32 size, offs, elem; char objectname[120]; char parname[120]; char *s; int sts; char buf[1024]; strcpy( objectname, attributename); s = strchr( objectname, '.'); strcpy( parname, s+1); *s = 0; sts = gdh_GetAttributeCharacteristics( attributename, &tid, &size, &offs, &elem); if ( EVEN(sts)) return sts; if ( !array_element) { sts = gdh_GetObjectInfo( attributename, buf, sizeof(buf)); if ( EVEN(sts)) return sts; print_attr( buf, arp, objectname, parname, tid, size, 0, elem, fp); } else { print_attr( object_p, arp, objectname, parname, tid, size, offs, elem, fp); } return 1; }
// // Check that the current selected item is valid for change // int XAttNav::check_attr( int *multiline, brow_tObject *node, char *name, char **init_value, int *size) { brow_tNode *node_list; int node_count; Item *base_item; pwr_tStatus sts; *init_value = 0; *multiline = 0; brow_GetSelectedNodes( brow->ctx, &node_list, &node_count); if ( !node_count) return XATT__NOSELECT; brow_GetUserData( node_list[0], (void **)&base_item); *node = node_list[0]; free( node_list); switch( base_item->type) { case xnav_eItemType_Attr: case xnav_eItemType_AttrArrayElem: case xnav_eItemType_Collect: { pwr_tTypeId a_tid; pwr_tUInt32 a_size, a_offs, a_elem; ItemBaseAttr *item = (ItemBaseAttr *)base_item; if ( item->noedit) return XATT__NOCHANGE; strcpy( name, item->attr); sts = gdh_GetAttributeCharacteristics( name, &a_tid, &a_size, &a_offs, &a_elem); if ( ODD(sts)) *size = cdh_TypeToMaxStrSize( (pwr_eType)item->type_id, a_size, a_elem); else *size = 80; return 1; } default: return XATT__NOCHANGE; } }
int main (int argc, char **argv) { pwr_tStatus sts; char *c; int cidopt = 0; pwr_tObjName cidstr; pwr_tAName astr; int i; if ( argc <= 1) { usage(); exit(1); } sts = gdh_Init("rt_gdhget"); if ( EVEN(sts)) { exit(sts); } for ( i = 1; i < argc; i++) { c = argv[i]; if ( *c == '-') { c++; switch ( *c) { case 'h': usage(); exit(0); case 'c': if ( argc <= i+1) { usage(); exit(1); } strncpy( cidstr, argv[i+1], sizeof(cidstr)); cidopt = 1; i++; break; } } else strcpy( astr, argv[i]); } if ( cidopt) { // Get the first object of class cidstr, and print the value of attribute // astr in this object pwr_tCid cid; pwr_tOid oid; pwr_tAttrRef aref, aaref; pwr_tTid a_tid; unsigned int a_size, a_offs, a_dim; void *a_valp; char str[256]; sts = gdh_ClassNameToId( cidstr, &cid); if ( EVEN(sts)) { exit(sts); } sts = gdh_GetClassList( cid, &oid); if ( EVEN(sts)) { exit(sts); } aref = cdh_ObjidToAref( oid); sts = gdh_ArefANameToAref( &aref, astr, &aaref); if ( EVEN(sts)) { exit(sts); } sts = gdh_GetAttributeCharAttrref( &aaref, &a_tid, &a_size, &a_offs, &a_dim); if ( EVEN(sts)) { exit(sts); } a_valp = calloc( 1, a_size); sts = gdh_GetObjectInfoAttrref( &aaref, a_valp, a_size); if ( EVEN(sts)) { free( a_valp); exit(sts); } sts = cdh_AttrValueToString( a_tid, a_valp, str, sizeof(str)); if ( EVEN(sts)) { free( a_valp); exit(sts); } printf( "%s\n", str); free( a_valp); exit(0); } else { // Print the value of the attriute in astr pwr_tTypeId a_tid; pwr_tUInt32 a_size, a_offs, a_elem; void *a_valp; char str[256]; sts = gdh_GetAttributeCharacteristics( astr, &a_tid, &a_size, &a_offs, &a_elem); if ( EVEN(sts)) { exit(sts); } a_valp = calloc( 1, a_size); sts = gdh_GetObjectInfo( astr, a_valp, a_size); if ( EVEN(sts)) { free( a_valp); exit(sts); } sts = cdh_AttrValueToString( a_tid, a_valp, str, sizeof(str)); if ( EVEN(sts)) { free( a_valp); exit(sts); } printf( "%s\n", str); free( a_valp); exit(0); } exit(1); }
void fastobject::open( double base_scantime) { pwr_tStatus sts; pwr_tUInt32 size, offs, elem; pwr_tTypeId type_id; pwr_tAName name; // Link to object sts = gdh_DLRefObjectInfoAttrref( &aref, (void **)&p, &p_dlid); if ( EVEN(sts)) throw co_error(sts); // Link to trigg object if ( cdh_ObjidIsNotNull( p->TriggObject.Objid)) { sts = gdh_DLRefObjectInfoAttrref( &p->TriggObject, (void **)&trigg, &trigg_dlid); if ( EVEN(sts)) { if ( p->Function & fast_mFunction_ManTrigg || p->Function & fast_mFunction_LevelTrigg) trigg = 0; else throw co_error(sts); } } // Link to attributes for ( int i = 0; i < FAST_CURVES; i++) { if ( cdh_ObjidIsNotNull( p->Attribute[i].Objid)) { sts = gdh_DLRefObjectInfoAttrref( &p->Attribute[i], (void **)&attributes[i], &attributes_dlid[i]); if ( EVEN(sts)) throw co_error(sts); // Get attribute type sts = gdh_AttrrefToName( &p->Attribute[i], name, sizeof( name), cdh_mName_volumeStrict); if ( EVEN(sts)) throw co_error(sts); sts = gdh_GetAttributeCharacteristics( name, &p->AttributeType[i], &attributes_size[i], &offs, &elem); if ( EVEN(sts)) throw co_error(sts); p->CurveValid[i] = true; } } // Link to time buffer if ( cdh_ObjidIsNotNull( p->TimeBuffer.Objid)) { sts = gdh_DLRefObjectInfoAttrref( &p->TimeBuffer, (void **)&time_buffer, &time_buffer_dlid); if ( EVEN(sts)) throw co_error(sts); // Get buffer size sts = gdh_AttrrefToName( &p->TimeBuffer, name, sizeof( name), cdh_mName_volumeStrict); if ( EVEN(sts)) throw co_error(sts); sts = gdh_GetAttributeCharacteristics( name, &type_id, &size, &offs, &elem); if ( EVEN(sts)) throw co_error(sts); if ( size < p->NoOfPoints * sizeof(pwr_tFloat32)) p->NoOfPoints = size / sizeof(pwr_tFloat32); } // Link to attribute buffers for ( int i = 0; i < FAST_CURVES; i++) { if ( cdh_ObjidIsNotNull( p->Buffers[i].Objid) && p->CurveValid[i]) { p->CurveValid[i] = false; sts = gdh_DLRefObjectInfoAttrref( &p->Buffers[i], (void **)&buffers[i], &buffers_dlid[i]); if ( EVEN(sts)) throw co_error(sts); p->CurveValid[i] = true; // Get buffer size sts = gdh_AttrrefToName( &p->Buffers[i], name, sizeof( name), cdh_mName_volumeStrict); if ( EVEN(sts)) throw co_error(sts); sts = gdh_GetAttributeCharacteristics( name, &type_id, &size, &offs, &elem); if ( EVEN(sts)) throw co_error(sts); if ( size < p->NoOfPoints * attributes_size[i]) p->NoOfPoints = size / attributes_size[i]; } } p->TriggMan = 0; p->Active = 0; p->Prepare = 0; p->TriggIndex = 0; if ( trigg) *trigg = 0; if ( p->ScanTime) scan_div = int( p->ScanTime / base_scantime + 0.5); else scan_div = 1; scan_base = base_scantime; }
int XNav::getAllMenuItems( xmenu_sMenuCall *ip, xmenu_sMenuItem **Item, pwr_tObjid objid, pwr_tUInt32 Level, int *nItems, int AddSeparator, pwr_sAttrRef *CurrentObject) { int sts; pwr_tCid classid; pwr_tObjid child; pwr_sMenuButton *mbp; pwr_sMenuCascade *mcp; pwr_sMenuRef *mrp; pwr_tStatus (*filter)( xmenu_sMenuCall *); int sensitive; int i; Level++; memset(*Item, 0, sizeof(**Item)); if(AddSeparator) { (*Item)->Level = Level; (*Item)->Item = xmenu_eMenuItem_Separator; (*Item)->MenuObject = pwr_cNObjid; (*Item)++; (*nItems)++; } else { sts = gdh_GetObjectClass( objid, &classid); if ( EVEN(sts)) return sts; if ( classid == pwr_eClass_MenuButton) { sts = gdh_ObjidToPointer( objid, (void **) &mbp); if ( EVEN(sts)) return sts; ip->ChosenItem = *nItems; for ( i = 0; i < 5; i++) { strcpy( (*Item)->FilterArguments[i], mbp->FilterArguments[i]); } // Call any filter method (*Item)->CurrentObject = *CurrentObject; sensitive = 1; if ( strcmp( mbp->FilterName, "") != 0) { sts = GetMethod( mbp->FilterName, &filter); if ( ODD(sts)) { sts = (filter) ( ip); if ( sts == XNAV__INSENSITIVE) sensitive = 0; } } else sts = XNAV__SUCCESS; if ( ODD(sts)) { (*Item)->Level = Level; (*Item)->Item = xmenu_eMenuItem_Button; (*Item)->MenuObject = objid; (*Item)->Flags.f.Sensitive = sensitive; if (strcmp( mbp->MethodName, "") == 0) (*Item)->Flags.f.Sensitive = 0; strcpy((*Item)->Name, mbp->ButtonName); strcpy( (*Item)->Method, mbp->MethodName); strcpy( (*Item)->Filter, mbp->FilterName); for ( i = 0; i < 5; i++) { strcpy( (*Item)->MethodArguments[i], mbp->MethodArguments[i]); } (*Item)++; (*nItems)++; } } else if ( classid == pwr_eClass_MenuSeparator) { (*Item)->Level = Level; (*Item)->Item = xmenu_eMenuItem_Separator; (*Item)->MenuObject = objid; (*Item)++; (*nItems)++; } else if ( classid == pwr_eClass_MenuCascade) { sts = gdh_ObjidToPointer( objid, (void **) &mcp); if ( EVEN(sts)) return sts; // Call any filter method (*Item)->CurrentObject = *CurrentObject; if ( strcmp( mcp->FilterName, "") != 0) { sts = GetMethod( mcp->FilterName, &filter); if ( ODD(sts)) { sts = (filter) ( ip); } } else sts = XNAV__SUCCESS; if ( ODD(sts)) { (*Item)->Level = Level; (*Item)->Item = xmenu_eMenuItem_Cascade; (*Item)->Flags.f.Sensitive = 1; strcpy((*Item)->Name, mcp->ButtonName); (*Item)->MenuObject = objid; (*Item)++; (*nItems)++; sts = gdh_GetChild( objid, &child); while( ODD(sts)) { sts = getAllMenuItems(ip, Item, child, Level, nItems, 0, CurrentObject); if ( EVEN(sts)) return sts; sts = gdh_GetNextSibling( child, &child); } } } else if ( classid == pwr_eClass_MenuRef && cdh_ObjidIsNull( CurrentObject->Objid)) { pwr_tAName aname; pwr_sAttrRef currentar; pwr_tCid current_cid; pwr_tTid a_tid; pwr_tUInt32 a_size, a_offs, a_elem; sts = gdh_ObjidToPointer( objid, (void **) &mrp); if ( EVEN(sts)) return sts; // Call any filter method (*Item)->CurrentObject = *CurrentObject; if ( strcmp( mrp->FilterName, "") != 0) { sts = GetMethod( mrp->FilterName, &filter); if ( ODD(sts)) { sts = (filter) ( ip); } } else sts = XNAV__SUCCESS; if ( ODD(sts)) { int create_object_button = 0; if ( strcmp( mrp->RefAttribute, "_SelfObject") == 0) { // Object entry for attributes char *s; sts = gdh_AttrrefToName( &ip->Pointed, aname, sizeof(aname), cdh_mName_volumeStrict); if ( EVEN(sts)) return sts; if ( (s = strrchr( aname, '.'))) *s = 0; sts = gdh_NameToAttrref( pwr_cNOid, aname, ¤tar); if ( EVEN(sts)) return sts; } else { sts = gdh_AttrrefToName( &ip->Pointed, aname, sizeof(aname), cdh_mName_volumeStrict); if ( EVEN(sts)) return sts; strcat( aname, "."); strcat( aname, mrp->RefAttribute); sts = gdh_GetAttributeCharacteristics( aname, &a_tid, &a_size, &a_offs, &a_elem); if ( ODD(sts)) { switch ( a_tid) { case pwr_eType_AttrRef: sts = gdh_GetObjectInfo( aname, ¤tar, sizeof(currentar)); break; case pwr_eType_Objid: { pwr_tOid oid; currentar = pwr_cNAttrRef; sts = gdh_GetObjectInfo( aname, &oid, sizeof(oid)); currentar = cdh_ObjidToAref( oid); break; } default: sts = 0; } } create_object_button = 0; } if ( ODD(sts) && cdh_ObjidIsNotNull( currentar.Objid)) { (*Item)->Level = Level; (*Item)->Item = xmenu_eMenuItem_Ref; (*Item)->Flags.f.Sensitive = 1; strcpy((*Item)->Name, mrp->ButtonName); (*Item)->MenuObject = objid; (*Item)++; (*nItems)++; // Create a label with current object name sts = gdh_AttrrefToName( ¤tar, aname, sizeof(aname), cdh_mNName); if ( ODD(sts) && create_object_button) { (*Item)->Level = Level; (*Item)->Item = xmenu_eMenuItem_Button; (*Item)->MenuObject = pwr_cNObjid; strncpy((*Item)->Name, aname, sizeof((*Item)->Name)); (*Item)->Name[sizeof((*Item)->Name)-1] = 0; (*Item)->MenuObject = pwr_cNObjid; (*Item)->CurrentObject = currentar; (*Item)->Flags.f.Sensitive = 1; strcpy( (*Item)->Method, "$Object-OpenObject"); (*Item)++; (*nItems)++; } sts = gdh_GetAttrRefTid( ¤tar, ¤t_cid); if ( EVEN(sts)) return sts; xmenu_eItemType item_type = ip->ItemType; if ( currentar.Flags.b.Object) ip->ItemType = xmenu_eItemType_Object; else ip->ItemType = xmenu_eItemType_AttrObject; sts = GetObjectMenu(ip, current_cid, Item, Level, nItems, 0, ¤tar); if ( EVEN(sts)) return sts; ip->ItemType = item_type; } } } } return XNAV__SUCCESS; }
static void pwrsrv_SubAdd( rpvd_sMsgSubAdd *msg) { rpvd_sMsgAny rmsg; pwr_tAName name; pwr_tUInt32 asize, aoffs, aelem; pwr_tTypeId atid; pwr_tStatus sts; pwrsrv_sSubItem *si; void *p; pwr_tRefId dlid; rmsg.Type = rpvd_eMsg_Status; rmsg.Id = msg->Id; /* Check that this rix doesn't exist */ for ( si = pwrsrv_sublist; si; si = si->next) { if ( si->rix == msg->Rix) { return; } } sts = gdh_ObjidToName( msg->Oid, name, sizeof(name), cdh_mName_volumeStrict); if ( EVEN(sts)) { rmsg.Status = sts; udp_Send( (char *)&rmsg, sizeof(rmsg)); return; } if ( strcmp( msg->Attribute, "") != 0) { strcat( name, "."); strcat( name, msg->Attribute); sts = gdh_GetAttributeCharacteristics( name, &atid, &asize, &aoffs, &aelem); if ( EVEN(sts)) { rmsg.Status = sts; udp_Send( (char *)&rmsg, sizeof(rmsg)); return; } } else { sts = gdh_GetObjectSize( msg->Oid, &asize); if ( EVEN(sts)) { rmsg.Status = sts; udp_Send( (char *)&rmsg, sizeof(rmsg)); return; } } /* Direct link to atttribute */ sts = gdh_RefObjectInfo( name, &p, &dlid, asize); if ( EVEN(sts)) { rmsg.Status = sts; udp_Send( (char *)&rmsg, sizeof(rmsg)); return; } /* Insert first in sublist */ si = (pwrsrv_sSubItem *) calloc( 1, sizeof(pwrsrv_sSubItem)); si->oid = msg->Oid; strcpy( si->attribute, msg->Attribute); si->size = asize; si->rix = msg->Rix; si->p = p; si->dlid = dlid; si->next = pwrsrv_sublist; if ( si->next) si->next->prev = si; pwrsrv_sublist = si; printf( "SubAdd: %d %s\n", msg->Rix, name); rmsg.Status = GDH__SUCCESS; udp_Send( (char *)&rmsg, sizeof(rmsg)); }
static int graph_object_collect_build( Graph *graph, pwr_sAttrRef *attrref) { pwr_sAttrRef *alist, *ap; int *is_attrp, *is_attr; int sts; char name[120]; double x1, y1; grow_sAttrInfo *grow_info, *grow_info_p; int grow_info_cnt; int i; grow_tObject scantime_button; grow_tObject hold_button; grow_tObject t1, l1; double z_width, z_height, z_descent; double name_width = 0; double trend_width = 48; double trend_height = 1.2; double y0 = 2.2; double x0 = 2; pwr_tTypeId attr_type; unsigned int attr_size, attr_offset, attr_dimension; GeDyn *dyn; char attr_name[120]; grow_sAttributes grow_attr; unsigned long mask; int trend_cnt = 0; if ( ! graph->get_current_objects_cb) return 0; sts = (graph->get_current_objects_cb) (graph->parent_ctx, &alist, &is_attr); if ( EVEN(sts)) return sts; if ( cdh_ObjidIsNull( alist->Objid)) return 0; graph->graph_object_data = 0; graph->graph_object_close = 0; grow_SetPath( graph->grow->ctx, 1, "pwr_exe:"); // Set graph attributes // Default color theme mask = grow_eAttr_color_theme; strcpy( grow_attr.color_theme, "$default"); grow_SetAttributes( graph->grow->ctx, &grow_attr, mask); grow_ReadCustomColorFile( graph->grow->ctx, 0); grow_SetBackgroundColor( graph->grow->ctx, glow_eDrawType_CustomColor1); // Scantime input field graph->create_node( NULL, "pwrct_valueinputsmallbg", x0, y0 - 1.3, 4, y0 - 1.3 + 1.2, &scantime_button); dyn = new GeDyn( graph); grow_SetUserData( scantime_button, (void *)dyn); dyn->set_dyn( ge_mDynType1_Value, ge_mDynType2_No, ge_mActionType1_ValueInput, ge_mActionType2_No); dyn->update_elements(); dyn->set_access( (glow_mAccess) 65535); dyn->set_attribute( scantime_button, "$local.ScanTime##Float32", 0); dyn->set_value_input( "%3.0f", 2, 10000000); // Hold button graph->create_node( "TrendHold", "pwrct_buttonsmalltoggle", x0 + trend_width/2 - 3./2, y0 - 1.4 , x0 + trend_width/2 + 3./2, y0 - 1.4 + 1.2, &hold_button); grow_SetAnnotation( hold_button, 1, "Hold", 4); dyn = new GeDyn( graph); grow_SetUserData( hold_button, (void *)dyn); dyn->set_access( (glow_mAccess) 65535); dyn->set_attribute( hold_button, "$local.TrendHold##Boolean", 0); // Zero text grow_CreateGrowText( graph->grow->ctx, "", "0", x0 + trend_width - 0.2, y0 - 0.3, glow_eDrawType_TextHelvetica, glow_eDrawType_CustomColor5, 3, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); ap = alist; is_attrp = is_attr; x1 = x0; y1 = y0; while( cdh_ObjidIsNotNull( ap->Objid)) { if ( *is_attrp) { sts = gdh_AttrrefToName( ap, name, sizeof(name), cdh_mNName); if ( EVEN(sts)) return sts; sts = gdh_GetAttributeCharacteristics( name, &attr_type, &attr_size, &attr_offset, &attr_dimension); if ( EVEN(sts)) return sts; switch ( attr_type) { case pwr_eType_Boolean: { grow_tObject trend; grow_CreateGrowTrend( graph->grow->ctx, "ActualValueTrend", x1, y1, trend_width, trend_height, glow_eDrawType_Color37, 0, glow_mDisplayLevel_1, 1, 1, glow_eDrawType_Color40, NULL, &trend); dyn = new GeDyn( graph); dyn->dyn_type1 = ge_mDynType1_Trend; dyn->update_dyntype( trend); dyn->update_elements(); grow_SetUserData( trend, (void *)dyn); grow_GetObjectAttrInfo( trend, NULL, &grow_info, &grow_info_cnt); strcpy( attr_name, name); strcat( attr_name, "##Boolean"); grow_GetUserData( trend, (void **)&dyn); strcpy( ((GeTrend *)dyn->elements)->attribute1, attr_name); strcpy( ((GeTrend *)dyn->elements)->timerange_attr, "$local.ScanTime##Float32"); strcpy( ((GeTrend *)dyn->elements)->hold_attr, "$local.TrendHold##Boolean"); grow_info_p = grow_info; for ( i = 0; i < grow_info_cnt; i++) { if ( strcmp( grow_info_p->name, "NoOfPoints") == 0) *(int *) grow_info_p->value_p = 200; else if ( strcmp( grow_info_p->name, "HorizontalLines") == 0) *(int *) grow_info_p->value_p = 0; else if ( strcmp( grow_info_p->name, "VerticalLines") == 0) *(int *) grow_info_p->value_p = 9; else if ( strcmp( grow_info_p->name, "CurveColor1") == 0) *(int *) grow_info_p->value_p = glow_eDrawType_CustomColor68; else if ( strcmp( grow_info_p->name, "MaxValue1") == 0) *(double *) grow_info_p->value_p = 1.2; else if ( strcmp( grow_info_p->name, "MinValue1") == 0) *(double *) grow_info_p->value_p = -0.1; grow_info_p++; } grow_FreeObjectAttrInfo( grow_info); // This will configure the curves grow_SetTrendScanTime( trend, 0.5); grow_SetObjectOriginalFillColor( trend, glow_eDrawType_CustomColor66); grow_SetObjectOriginalBorderColor( trend, glow_eDrawType_CustomColor67); grow_GetTextExtent( graph->grow->ctx, name, strlen(name), glow_eDrawType_TextHelvetica, 4, glow_eFont_LucidaSans, &z_width, &z_height, &z_descent); grow_CreateGrowText( graph->grow->ctx, "", name, x1 + trend_width + 1, y1 + trend_height/2 + z_height/2, glow_eDrawType_TextHelvetica, glow_eDrawType_CustomColor5, 4, glow_eFont_LucidaSans, glow_mDisplayLevel_1, NULL, &t1); if ( z_width > name_width) name_width = z_width; trend_cnt++; y1 += trend_height; break; } default: ; } if ( trend_cnt >= MAX_TREND_OBJECTS) break; } ap++; is_attrp++; } free( alist); free( is_attr); // Draw separator lines between name texts y1 = y0; x1 = x0 + trend_width; grow_CreateGrowLine( graph->grow->ctx, "", x0 + trend_width, y1, x0 + trend_width + name_width + 2, y1, glow_eDrawType_CustomColor4, 1, 0, NULL, &l1); for ( i = 0; i < trend_cnt; i++) { y1 += trend_height; grow_CreateGrowLine( graph->grow->ctx, "", x0 + trend_width, y1, x0 + trend_width + name_width + 2, y1, glow_eDrawType_CustomColor4, 1, 0, NULL, &l1); } // Draw frame grow_CreateGrowRect( graph->grow->ctx, "R1", x0 - 1.5, y0 - 2.7, trend_width + name_width + 5.5, 1, glow_eDrawType_CustomColor3, 1, 0, glow_mDisplayLevel_1, 1, 0, 0, glow_eDrawType_CustomColor3, NULL, &l1); grow_CreateGrowRect( graph->grow->ctx, "R2", x0 - 1.5, y0 + trend_cnt * trend_height + 0.5, trend_width + name_width + 5.5, 5, glow_eDrawType_CustomColor3, 1, 0, glow_mDisplayLevel_1, 1, 0, 0, glow_eDrawType_CustomColor3, NULL, &l1); grow_CreateGrowRect( graph->grow->ctx, "R3", x0 + trend_width + name_width + 2, y0 - 1.7, 2, y0 + trend_cnt * trend_height + 0.9, glow_eDrawType_CustomColor3, 1, 0, glow_mDisplayLevel_1, 1, 0, 0, glow_eDrawType_CustomColor3, NULL, &l1); grow_CreateGrowRect( graph->grow->ctx, "R4", x0 - 1.5, y0 - 1.7, 1, y0 + trend_cnt * trend_height + 0.9, glow_eDrawType_CustomColor3, 1, 0, glow_mDisplayLevel_1, 1, 0, 0, glow_eDrawType_CustomColor3, NULL, &l1); grow_SetLayout( graph->grow->ctx, x0 - 1, y0 - 2.3, x0 + trend_width + name_width + 3, y0 + trend_cnt * trend_height + 1.5); // Set graph attributes mask = grow_eAttr_double_buffer_on; grow_attr.double_buffer_on = 1; grow_SetAttributes( graph->grow->ctx, &grow_attr, mask); return 1; }