Quintiq file version 2.0
|
#parent: CustomDrawComponentSupplyChainVisualization/CustomDrawDataLayerNode
|
Response OnDrawObject (
|
shadow[SCVNode] object
|
) id:Response_CustomDrawComponentSupplyChainVisualization_CustomDrawDataLayerNode_OnDrawObject
|
{
|
#keys: '[132894.0.851837207]'
|
Body:
|
[*
|
// Draw SCVNode
|
|
// Drawing parameters, node label, node title, label width, title width
|
scvconfig := DataHolderSCVConfiguration.Data();
|
nodesize := scvconfig.NodeSize();
|
|
nodetitle := ''
|
nodelabel := ''
|
iconimage := '';
|
textformat := TextFormat::Construct( TextFormat::AlignBottom(), TextFormat::AlignCenter() );
|
|
// Specify labels, iconimage based on draw type
|
if( object.istype( shadow[SCVPISPIPNode] ) )
|
{
|
pisp := object.astype( shadow[SCVPISPIPNode] ).ProductInStockingPointInPeriod().ProductInStockingPoint_MP();
|
nodetitle := pisp.Product_MP().Name();
|
nodelabel := pisp.StockingPoint_MP().Name()
|
iconimage := ifexpr( pisp.Product_MP().IconName() <> '', pisp.Product_MP().IconName(), 'PRODUCT2' );
|
|
}
|
else if( object.istype( shadow[SCVRoutingStepNode] ) )
|
{
|
routingStep := select( object.astype( shadow[SCVRoutingStepNode] ), OperationInNode.Operation.RoutingStep, rs, true );
|
nodelabel := routingStep.Name();
|
iconimage := ifexpr( routingStep.Operation( relsize ) > 1, 'SIZES', 'SHAPE_SQUARE_BLUE' );
|
}
|
else if( object.istype( shadow[SCVLaneNode] ) )
|
{
|
lane := object.astype( shadow[SCVLaneNode] ).Lane();
|
nodelabel := lane.Name();
|
iconimage := 'DELIVERY_AMBER';
|
}
|
else if( object.istype( shadow[SCVISNode] ) )
|
{
|
nodelabel := object.Name();
|
iconimage := 'HAND_TRUCK_BOX';
|
}
|
else if( object.istype( shadow[SCVSDNode] ) )
|
{
|
node := object.astype( shadow[SCVSDNode] );
|
nodelabel := object.Name();
|
iconimage := ifexpr( node.ProductInStockingPointInPeriod().GetAreAllAssociatedSDIPsFulfilled(), 'DOCUMENT', 'DOCUMENT_DIRTY' );
|
}
|
|
// Text width, derived from horizontal offset
|
textWidth := floor( scvconfig.OffsetX() / 2 );
|
textOffsetX := floor( ( nodesize - textWidth ) / 2 );
|
textHeight := floor( scvconfig.OffsetY() / 2 );
|
|
// Draw node
|
if( scvconfig.IsUsingIconName() or not object.istype( shadow[SCVPISPIPNode] ) )
|
{
|
surface.Image( region.Left(), region.Top(), nodesize, nodesize, iconimage )
|
}
|
else
|
{
|
node := object.astype( shadow[SCVPISPIPNode] );
|
penWidth := 2;
|
|
if( node.ProductInStockingPointInPeriod().istype( ProductInStockingPointInPeriodPlanning )
|
and not node.ProductInStockingPointInPeriod().astype( ProductInStockingPointInPeriodPlanning ).IsValidPlannedBalance() ) // violation, no color with red border
|
{
|
// Draw planning violation indicator
|
surface.Pen().Color( ColorScheme.SCVNodeViolation() );
|
|
textformat := TextFormat::Construct( TextFormat::AlignCentered() );
|
surface.TextColor( ColorScheme.SCVNodeViolation() );
|
surface.TextZoom( region.Left(), region.Top(), nodesize, nodesize, '!', textformat );
|
}
|
else if( object.IsRoot() ) // root color, with border
|
{
|
surface.Pen().Color( Color::Black() )
|
surface.Brush().Color( ColorScheme.SCVRootNode() )
|
}
|
else // normal node, node color, no border
|
{
|
penWidth := 0;
|
surface.Brush().Color( ColorScheme.SCVNode() );
|
}
|
|
surface.Pen().Width( penWidth );
|
circle := Shape::Circle( region.Left(), region.Top(), nodesize );
|
surface.Fill( circle );
|
surface.Draw( circle );
|
}
|
|
// Update pen parameters
|
surface.Font().Name( scvconfig.FontName() )
|
.Size(scvconfig.FontSize() );
|
surface.TextColor( Color::Black() );
|
|
// Draw text
|
if( object.IsRoot() )
|
{
|
surface.Font().Bold( true );
|
|
// Draw period below the root node
|
periodStart := scvconfig.Period_MP().StartDate();
|
periodString := periodStart.Format( 'D-MM-YOnMax(-)OnMin(-)' );
|
|
nodelabel := nodelabel + String::NewLine() + periodString;
|
}
|
|
// For node title, we define a region above the top of the node
|
// then align it bottom, so that the text sticks to the top of the node
|
// Draw node title
|
surface.TextZoom( region.Left() + textOffsetX, // X
|
region.Top() - textHeight, // Y
|
textWidth, // Width
|
textHeight, // Height
|
nodetitle, // Text
|
textformat ); // Text format
|
|
// For text label, we make the draw region starts at the bottom of the node then align it top, so that
|
// it sticks to the bottom of the node
|
textformat := TextFormat::Construct( TextFormat::AlignTop(), TextFormat::AlignCenter() );
|
// Draw node label
|
surface.TextZoom( region.Left() + textOffsetX,
|
region.Bottom(),
|
textWidth,
|
textHeight,
|
nodelabel,
|
textformat );
|
|
// Draw indication for stream limit hit
|
isUpstreamLimitHit := object.IsUpstream() and object.IsDepthLimitMet();
|
isDownstreamLimitHit := not object.IsUpstream() and object.IsDepthLimitMet();
|
|
// Special handling for root
|
if( object.IsRoot() )
|
{
|
node := object.astype( shadow[SCVPISPIPNode] );
|
isUpstreamLimitHit := scvconfig.UpstreamDepthLimit() = 0
|
and ( ( FormSupplyChainVisualization.GetInputOutputs( node.ProductInStockingPointInPeriod(), true /*isupstream*/ ).Size() > 0 )
|
or node.ProductInStockingPointInPeriod().InventorySupplyQuantity() > 0 );
|
isDownstreamLimitHit := scvconfig.DownstreamDepthLimit() = 0
|
and ( ( FormSupplyChainVisualization.GetInputOutputs( node.ProductInStockingPointInPeriod(), false /*isupstream*/ ).Size() > 0 )
|
or node.ProductInStockingPointInPeriod().SalesDemandInPeriodBase( relsize ) > 0 );
|
}
|
|
textformat := TextFormat::Construct( TextFormat::AlignCentered() );
|
|
if( isUpstreamLimitHit )
|
{
|
surface.Font().Bold( true );
|
surface.TextColor( ColorScheme.SCVEdge() );
|
|
surface.TextZoom( region.Left() + 2 * -nodesize,
|
region.Top(),
|
nodesize,
|
nodesize,
|
'...',
|
textformat );
|
}
|
|
if( isDownstreamLimitHit )
|
{
|
surface.Font().Bold( true );
|
surface.TextColor( ColorScheme.SCVEdge() );
|
|
surface.TextZoom( region.Left() + 2 * nodesize,
|
region.Top(),
|
nodesize,
|
nodesize,
|
'...',
|
textformat );
|
}
|
*]
|
CanBindMultiple: false
|
DefinitionID: 'Responsedef_CustomDrawDataLayer_OnDrawObject'
|
}
|