views:

667

answers:

2

I want a rather simple (and cheap) solution, just for presentation purposes (and just to show the task duration bars - no connection lines between them). So, I am not interested in buying some advanced custom control like this for example. Have any of you ever used something like this? Are there any code samples available?

+4  A: 

I would have pointed to Buck Woolley's dwExtreme site for an example of how to do a gantt in native DataWindow. However, "simple" I don't think is in your future if you want to roll your own. In fact, I'll be pleasantly surprised if someone writes a posting that includes a full description; I think it would take pages. (I'd be happy if someone proved me wrong.) In the meantime, here are some DataWindow basics I think you would need:

  • You can create an external DataWindow whose data source is not tied to a table
  • Columns in the data set do not have to be shown on the user interface
  • Columns in the data set can be used in expressions to evaluate attributes, so you could have a column for each of the following attributes of a rectangle:
    • x
    • width
    • color

I'd expect this to be a lot of work and time, and very likely to be worth the purchase the component (unless your time is valued at next to nothing, which in some IT shops is close to true).

Good luck,

Terry

Terry
Thank you. However I didn't find a way to access the code behind those interesting implementations. Nor did I find a way to purchase one (in Download/Purchase tab). Meanwhile I did find this one http://www.activegraphic.co.uk/
gd047
Sorry, was definitely not clear on the dwExtreme product. It's not free, which is what led to the comment at the end about being better off purchasing it or some other component. I see what you mean about problems purchasing, but there's an email on the Contact page. The dwExtreme product has a very good, very long standing reputation in the PB community. However, if you've found what you need, that's great.
Terry
"unless your time is valued at next to nothing, which in some IT shops is close to true"If I could, I'd give +1 for the answer, then another +1 for that comment alone.
Bernard Dy
Get happy! It's a ridiculously small amount of code.
Hugh Brackett
+2  A: 

Gantt chart in PowerBuilder

You can make a simple Gantt chart with a Stacked Bar Graph (BarStacked (5) in the painter). The trick is to create a dummy series to space the bar out where you want it and make the dummy bar the same color as the graph's background (BackColor). It turns out you also need another dummy series with a small value to sit on the axis. Otherwise when you change the color of the bar that's doing the spacing, the axis line gets cut off. I found that .04 works well for this value.

Create the DataWindow

(This assumes familarity with the DataWindow Wizard. Refer to the PowerBuilder User's Guide for more information on creating graphs in DataWindows)

Click the icon for the new object wizard. Create a Graph DataWindow with an External data source. Create columns task type string(20), ser type string(1), and days type number. Set the Category to the task column and the Values to the days column. Click the Series button and select ser for the series. Don't bother with the title, and select the Stacked Bar graph type. When the painter opens, save the DataWindow. On the General tab in the Painter, change the Legend to None (0). On the Axis tab, select the Category axis, then set the sort to Unsorted (0). Select the Value axis then set the sort to Unsorted (0). Select the Series axis and set the sort to Ascending (1). Save the DataWindow.

Create the Window

Create a window and place a DataWindow control, dw_1. Set the data object to your graph DataWindow. Place the following in the open event (or pfc_postopen if using PFC).

try

    dw_1.setRedraw(FALSE)

    // LOAD DATA HERE

    dw_1.object.gr_1.title = 'Project PBL Pusher'
    dw_1.object.gr_1.category.label = 'Phase'
    dw_1.object.gr_1.values.label = 'Project-Days'


catch (runtimeerror re)
    if isvalid(gnv_app.inv_debug) then gnv_app.inv_debug.of_message(re.text)    // could do better
finally
    dw_1.setRedraw(TRUE)
end try

You would load the data for your chart where the comment says // LOAD DATA HERE

Script the graphcreate Event

Add an new event to dw_1. Select pbm_dwngraphcreate for the Event ID. I like to name these events by removing the pbm_dwn prefix so I use graphcreate. Add the following code to the event.

string ls_series
long li_color

try


    li_color=long(dw_1.object.gr_1.backcolor)

    // note first series is a dummy with a small value (0.04 seems to work) to keep the line from being hidden
    ls_series = dw_1.seriesName("gr_1", 2)
    if 0 = len(ls_series) then return       // maybe show error message

    // will return -1 when you set color same as the graph's backcolor but it sets the color
    dw_1.setSeriesStyle("gr_1", ls_series, BackGround!, li_color)   // the box
    dw_1.setSeriesStyle("gr_1", ls_series, ForeGround!, li_color)   // the inside

catch (runtimeerror re)
    if isvalid(gnv_app.inv_debug) then gnv_app.inv_debug.of_message(re.text)    // could do better
end try

Data for the Graph

Load the data with the categories in the reverse order of what you want. For each Task, insert 3 rows and set the series to a, b, and c, respectively. For series a in each task, set a small value. I used 0.04. You may have to experiment. For series b in each task, set the number of days before start. For series c, set the number of days. Below is the data in the sample DataWindow.

    Task    Ser Days
    ----    --- ----
    Test    a   0.04
    Test    b   24
    Test    c   10
    Develop a   0.04
    Develop b   10
    Develop c   14
    Design  a   0.04
    Design  b   0
    Design  c   10

Sample DataWindow

Below is the source for a sample DataWindow in export format. You should be able to import into any version >= PB 10. Copy the code and paste it into a file with an SRD extension, then import it.

HA$PBExportHeader$d_graph.srd
release 10;
datawindow(units=0 timer_interval=0 color=1073741824 processing=3 HTMLDW=no print.printername="" print.documentname="" print.orientation = 1 print.margin.left = 110 print.margin.right = 110 print.margin.top = 96 print.margin.bottom = 96 print.paper.source = 0 print.paper.size = 0 print.canusedefaultprinter=yes print.prompt=no print.buttons=no print.preview.buttons=no print.cliptext=no print.overrideprintjob=no print.collate=yes hidegrayline=no )
summary(height=0 color="536870912" )
footer(height=0 color="536870912" )
detail(height=0 color="536870912" )
table(column=(type=char(10) updatewhereclause=yes name=task dbname="task" )
 column=(type=char(1) updatewhereclause=yes name=ser dbname="ser" )
 column=(type=number updatewhereclause=yes name=days dbname="days" )
 )
data("Test","a", 0.04,"Test","b", 24,"Test","c", 10,"Develop","a", 0.04,"Develop","b", 10,"Develop","c", 14,"Design","a", 0.04,"Design","b", 0,"Design","c", 10,) 
graph(band=background height="1232" width="2798" graphtype="5" perspective="2" rotation="-20" color="0" backcolor="16777215" shadecolor="8355711" range= 0 border="3" overlappercent="0" spacing="100" plotnulldata="0" elevation="20" depth="100"x="0" y="0" height="1232" width="2798"  name=gr_1 visible="1"  sizetodisplay=1  series="ser"  category="task"  values="days"  title="Title"  title.dispattr.backcolor="553648127"  title.dispattr.alignment="2"  title.dispattr.autosize="1"  title.dispattr.font.charset="0"  title.dispattr.font.escapement="0"  title.dispattr.font.face="Tahoma"  title.dispattr.font.family="2"  title.dispattr.font.height="0"  title.dispattr.font.italic="0"  title.dispattr.font.orientation="0"  title.dispattr.font.pitch="2"  title.dispattr.font.strikethrough="0"  title.dispattr.font.underline="0"  title.dispattr.font.weight="700"  title.dispattr.format="[general]"  title.dispattr.textcolor="0"  title.dispattr.displayexpression="title"  legend="0"  legend.dispattr.backcolor="536870912"  legend.dispattr.alignment="0"  legend.dispattr.autosize="1"  legend.dispattr.font.charset="0"  legend.dispattr.font.escapement="0"  legend.dispattr.font.face="Tahoma"  legend.dispattr.font.family="2"  legend.dispattr.font.height="0"  legend.dispattr.font.italic="0"  legend.dispattr.font.orientation="0"  legend.dispattr.font.pitch="2"  legend.dispattr.font.strikethrough="0"  legend.dispattr.font.underline="0"  legend.dispattr.font.weight="400"  legend.dispattr.format="[general]"  legend.dispattr.textcolor="553648127"  legend.dispattr.displayexpression="' '" 
    series.autoscale="1" 
    series.displayeverynlabels="0"  series.droplines="0"  series.frame="1"  series.label="(None)"  series.majordivisions="0"  series.majorgridline="0"  series.majortic="3"  series.maximumvalue="0"  series.minimumvalue="0"  series.minordivisions="0"  series.minorgridline="0"  series.minortic="1"  series.originline="1"  series.primaryline="1"  series.roundto="0"  series.roundtounit="0"  series.scaletype="1"  series.scalevalue="1"  series.secondaryline="0"  series.shadebackedge="0"  series.dispattr.backcolor="536870912"  series.dispattr.alignment="0"  series.dispattr.autosize="1"  series.dispattr.font.charset="0"  series.dispattr.font.escapement="0"  series.dispattr.font.face="Tahoma"  series.dispattr.font.family="2"  series.dispattr.font.height="0"  series.dispattr.font.italic="0"  series.dispattr.font.orientation="0"  series.dispattr.font.pitch="2"  series.dispattr.font.strikethrough="0"  series.dispattr.font.underline="0"  series.dispattr.font.weight="400"  series.dispattr.format="[general]"  series.dispattr.textcolor="0"  series.dispattr.displayexpression="series"  series.labeldispattr.backcolor="553648127"  series.labeldispattr.alignment="2"  series.labeldispattr.autosize="1"  series.labeldispattr.font.charset="0"  series.labeldispattr.font.escapement="0"  series.labeldispattr.font.face="Tahoma"  series.labeldispattr.font.family="2"  series.labeldispattr.font.height="0"  series.labeldispattr.font.italic="0"  series.labeldispattr.font.orientation="0"  series.labeldispattr.font.pitch="2"  series.labeldispattr.font.strikethrough="0"  series.labeldispattr.font.underline="0"  series.labeldispattr.font.weight="400"  series.labeldispattr.format="[general]"  series.labeldispattr.textcolor="0"  series.labeldispattr.displayexpression=" seriesaxislabel"  series.sort="1" 
    category.autoscale="1" 
    category.displayeverynlabels="0"  category.droplines="0"  category.frame="1"  category.label="(None)"  category.majordivisions="0"  category.majorgridline="0"  category.majortic="3"  category.maximumvalue="0"  category.minimumvalue="0"  category.minordivisions="0"  category.minorgridline="0"  category.minortic="1"  category.originline="0"  category.primaryline="1"  category.roundto="0"  category.roundtounit="0"  category.scaletype="1"  category.scalevalue="1"  category.secondaryline="0"  category.shadebackedge="1"  category.dispattr.backcolor="556870912"  category.dispattr.alignment="1"  category.dispattr.autosize="1"  category.dispattr.font.charset="0"  category.dispattr.font.escapement="0"  category.dispattr.font.face="Tahoma"  category.dispattr.font.family="2"  category.dispattr.font.height="0"  category.dispattr.font.italic="0"  category.dispattr.font.orientation="0"  category.dispattr.font.pitch="2"  category.dispattr.font.strikethrough="0"  category.dispattr.font.underline="0"  category.dispattr.font.weight="400"  category.dispattr.format="[general]"  category.dispattr.textcolor="0"  category.dispattr.displayexpression="category"  category.labeldispattr.backcolor="556870912"  category.labeldispattr.alignment="2"  category.labeldispattr.autosize="1"  category.labeldispattr.font.charset="0"  category.labeldispattr.font.escapement="900"  category.labeldispattr.font.face="Tahoma"  category.labeldispattr.font.family="2"  category.labeldispattr.font.height="0"  category.labeldispattr.font.italic="0"  category.labeldispattr.font.orientation="900"  category.labeldispattr.font.pitch="2"  category.labeldispattr.font.strikethrough="0"  category.labeldispattr.font.underline="0"  category.labeldispattr.font.weight="400"  category.labeldispattr.format="[general]"  category.labeldispattr.textcolor="0"  category.labeldispattr.displayexpression="categoryaxislabel"  category.sort="0" 
    values.autoscale="1" 
    values.displayeverynlabels="0"  values.droplines="0"  values.frame="1"  values.label="(None)"  values.majordivisions="0"  values.majorgridline="0"  values.majortic="3"  values.maximumvalue="1500"  values.minimumvalue="0"  values.minordivisions="0"  values.minorgridline="0"  values.minortic="1"  values.originline="1"  values.primaryline="1"  values.roundto="0"  values.roundtounit="0"  values.scaletype="1"  values.scalevalue="1"  values.secondaryline="0"  values.shadebackedge="0"  values.dispattr.backcolor="556870912"  values.dispattr.alignment="2"  values.dispattr.autosize="1"  values.dispattr.font.charset="0"  values.dispattr.font.escapement="0"  values.dispattr.font.face="Tahoma"  values.dispattr.font.family="2"  values.dispattr.font.height="0"  values.dispattr.font.italic="0"  values.dispattr.font.orientation="0"  values.dispattr.font.pitch="2"  values.dispattr.font.strikethrough="0"  values.dispattr.font.underline="0"  values.dispattr.font.weight="400"  values.dispattr.format="[General]"  values.dispattr.textcolor="0"  values.dispattr.displayexpression="value"  values.labeldispattr.backcolor="553648127"  values.labeldispattr.alignment="2"  values.labeldispattr.autosize="1"  values.labeldispattr.font.charset="0"  values.labeldispattr.font.escapement="0"  values.labeldispattr.font.face="Tahoma"  values.labeldispattr.font.family="2"  values.labeldispattr.font.height="0"  values.labeldispattr.font.italic="0"  values.labeldispattr.font.orientation="0"  values.labeldispattr.font.pitch="2"  values.labeldispattr.font.strikethrough="0"  values.labeldispattr.font.underline="0"  values.labeldispattr.font.weight="700"  values.labeldispattr.format="[general]"  values.labeldispattr.textcolor="0"  values.labeldispattr.displayexpression="valuesaxislabel" )
htmltable(border="1" )
htmlgen(clientevents="1" clientvalidation="1" clientcomputedfields="1" clientformatting="0" clientscriptable="0" generatejavascript="1" encodeselflinkargs="1" netscapelayers="0" )
xhtmlgen() cssgen(sessionspecific="0" )
xmlgen(inline="0" )
xsltgen()
jsgen()
export.xml(headgroups="1" includewhitespace="0" metadatatype=0 savemetadata=0 )
import.xml()
export.pdf(method=0 distill.custompostscript="0" xslfop.print="0" )
export.xhtml()
Hugh Brackett
Oops. I accidently left in some PFC-ism. Just comment out the lines that reference gnv_app. You'll want some real error handling anyway.
Hugh Brackett
Thank you, I ll give it a try. As regards PFC, I also use it.
gd047