GD::Graph によるグラフ生成

前へ << 画像生成 全文検索 >> 次へ

GD::Graph

GD::Graph は perl モジュールで、perl から gd ライブラリを利用してグラフを生成するためのものです。

で、これを解説しようと思ったのですが、マニュアルを読んでも機能が理解できず腹が立ったので、 機能検証プログラムを作ってみました。

実行はこちらから。
http://X68000.q-e-d.net/~68user/webcgi/sample/perl/graph-maker.cgi
ソースは以下のとおり。解説はそのうち (といっても、解説すべきところもあまりないのですが)。

graph-maker.cgi (実行結果)

    1: #!/usr/local/bin/perl
    2: 
    3: # $Id: graph-maker.cgi,v 1.11 2007/06/21 17:49:11 68user Exp $
    4: #
    5: # Written by 68user 
    6: #   http://X68000.q-e-d.net/~68user/
    7: 
    8: use strict;
    9: use Jcode;
   10: 
   11: use HTML::Template;
   12: 
   13: use GD;
   14: use GD::Graph;
   15: use GD::Graph::colour;
   16: 
   17: use GD::Graph::lines;
   18: use GD::Graph::linespoints;
   19: use GD::Graph::bars;
   20: use GD::Graph::hbars;
   21: use GD::Graph::points;
   22: use GD::Graph::area;
   23: use GD::Graph::pie;
   24: 
   25: my %gd_defs = (
   26:                graph_type => {
   27:                    depend_check_only => 1,
   28:                    affect => {
   29:                        'lines,linespoints,points,pie' => {
   30:                            cumulate       => 0,
   31:                        },
   32:                        'bars,hbars,area,points,pie' => {
   33:                            line_width     => 0,
   34:                        },
   35:                        'lines,bars,hbars,area,pie' => {
   36:                            marker_size    => 0,
   37:                        },
   38:                        'lines,linespoints,bars,hbars,area,points' => {
   39:                            value_font     => 0,
   40:                            pie_height     => 0,
   41:                            label          => 0,
   42:                            labelclr       => 0,
   43:                            start_angle    => 0,
   44:                            suppress_angle => 0,
   45:                        },
   46:                        'lines,linespoints,area,points,pie' => {
   47:                            shadowclr     => 0,
   48:                            shadow_depth  => 0,
   49:                            bar_spacing   => 0,
   50:                        },
   51:                        
   52:                        'pie' => {
   53:                            x_axis_font    => 0,
   54:                            x_tick_length  => 0,
   55:                            x_long_ticks   => 0,
   56:                            y_axis_font    => 0,
   57:                            y_tick_length  => 0,
   58:                            y_long_ticks   => 0,
   59:                            x_ticks        => 0,
   60:                            zero_axis      => 0,
   61:                            zero_axis_only => 0,
   62: 
   63:                            x_label              => 0,
   64:                            x_label_font         => 0,
   65:                            x_label_skip         => 0,
   66:                            x_label_offset       => 0,
   67:                            x_label_position     => 0,
   68:                            x_labels_vertical    => 0,
   69:                            y_label              => 0,
   70:                            y_label_font         => 0,
   71:                            y_label_skip         => 0,
   72:                            y_label_offset       => 0,
   73:                            y_label_position     => 0,
   74:                            y_tick_number        => 0,
   75:                            no_axes              => 0,
   76:                            box_axis             => 0,
   77:                            legendclr            => 0,
   78:                            legend_placement     => 0,
   79:                            legend_spacing       => 0,
   80:                            legend_marker_width  => 0,
   81:                            legend_marker_height => 0,
   82:                            axis_space           => 0,
   83:                            y_max_value          => 0,
   84:                            y_min_value          => 0,
   85:                            x_plot_values        => 0,
   86:                            y_plot_values        => 0,
   87:                            show_values          => 0,
   88:                            values_vertical      => 0,
   89:                            values_space         => 0,
   90:                        },
   91:                    },
   92:                },
   93:                title => {
   94:                    desc => 'グラフタイトル',
   95:                    default_value => 'this is title',
   96:                    type => 'string',
   97:                    input_size => 10,
   98:                    comment => 'グラフ上部に記述するタイトル文字列',
   99:                },
  100:                title_font => {
  101:                    desc => 'タイトルフォント',
  102:                    shortdesc => 'フォント',
  103:                    type => 'font',
  104:                    default_value => 'gdLargeFont',
  105:                },
  106:                width => {
  107:                    desc => '画像の幅',
  108:                    shortdesc => '幅',
  109:                    type => 'digit',
  110:                    default_value => 400,
  111:                    min_value => 50,
  112:                    max_value => 1000,
  113:                    input_size => 6,
  114:                    comment => '生成するグラフ画像の幅 (グラフの幅ではなく画像の幅)',
  115:                },
  116:                height => {
  117:                    desc => '画像の高さ',
  118:                    shortdesc => '高さ',
  119:                    type => 'digit',
  120:                    default_value => 200,
  121:                    min_value => 50,
  122:                    max_value => 1000,
  123:                    input_size => 6,
  124:                    comment => '生成するグラフ画像の高さ (グラフの高さではなく画像の高さ)',
  125:                },
  126:                t_margin => {
  127:                    desc => '上マージン',
  128:                    type => 'digit',
  129:                    default_value => 0,
  130:                    input_size => 3,
  131:                },
  132:                b_margin => {
  133:                    desc => '下マージン',
  134:                    type => 'digit',
  135:                    default_value => 0,
  136:                    input_size => 3,
  137:                },
  138:                l_margin => {
  139:                    desc => '左マージン',
  140:                    type => 'digit',
  141:                    default_value => 0,
  142:                    input_size => 3,
  143:                },
  144:                r_margin => {
  145:                    desc => '右マージン',
  146:                    type => 'digit',
  147:                    default_value => 0,
  148:                    input_size => 3,
  149:                },
  150:                x_label => {
  151:                    desc => 'X軸ラベル',
  152:                    shortdesc => 'ラベル',
  153:                    type => 'string',
  154:                    default_value => 'X label',
  155:                    input_size => 8,
  156:                },
  157:                y_label => {
  158:                    desc => 'Y軸ラベル',
  159:                    shortdesc => 'ラベル',
  160:                    type => 'string',
  161:                    default_value => 'Y label',
  162:                    input_size => 8,
  163:                },
  164:                x_label_font => {
  165:                    desc => 'X軸ラベルフォント',
  166:                    shortdesc => 'フォント',
  167:                    type => 'font',
  168:                    default_value => 'gdSmallFont',
  169:                },
  170:                y_label_font => {
  171:                    desc => 'Y軸ラベルフォント',
  172:                    shortdesc => 'フォント',
  173:                    type => 'font',
  174:                    default_value => 'gdSmallFont',
  175:                },
  176:                x_axis_font => {
  177:                    desc => 'X軸目盛りフォント',
  178:                    shortdesc => 'フォント',
  179:                    type => 'font',
  180:                    default_value => 'gdSmallFont',
  181:                    comment => 'この例ではグラフ下部の 10, 20, 30 などのフォント',
  182:                },
  183:                y_axis_font => {
  184:                    desc => 'Y軸目盛りフォント',
  185:                    shortdesc => 'フォント',
  186:                    type => 'font',
  187:                    default_value => 'gdSmallFont',
  188:                    comment => 'この例ではグラフ左の 0, 500, 1000 などのフォント',
  189:                },
  190:                x_ticks => {
  191:                    desc => 'X軸目盛り有無',
  192:                    type => 'option',
  193:                    option_values => {
  194:                        1 => {
  195:                            desc  => 'あり',
  196:                            is_default => 1,
  197:                        },
  198:                        0 => {
  199:                            desc  => 'なし',
  200:                        },
  201:                    },
  202:                    affect => {
  203:                        0 => {
  204:                            x_long_ticks  => 0,
  205:                            x_tick_length => 0,
  206:                        },
  207:                    },
  208:                },
  209:                x_long_ticks => {
  210:                    desc => 'X軸目盛り線延長',
  211:                    shortdesc => '線延長',
  212:                    type => 'option',
  213:                    option_values => {
  214:                        1 => {
  215:                            desc  => 'する',
  216:                        },
  217:                        0 => {
  218:                            desc  => 'しない',
  219:                            is_default => 1,
  220:                        },
  221:                    },
  222:                },
  223:                y_long_ticks => {
  224:                    desc => 'Y軸目盛り線延長',
  225:                    shortdesc => '線延長',
  226:                    type => 'option',
  227:                    option_values => {
  228:                        1 => {
  229:                            desc  => 'する',
  230:                        },
  231:                        0 => {
  232:                            desc  => 'しない',
  233:                            is_default => 1,
  234:                        },
  235:                    },
  236:                },
  237: #              x_tick_number => {
  238: #                  desc => 'X軸目盛り個数',
  239: #                  type => 'digit',
  240: #                  default_value => 5,
  241: #                  input_size => 3,
  242: #              },
  243:                x_tick_length => {
  244:                    desc => 'X軸目盛り線長',
  245:                    shortdesc => '線長',
  246:                    type => 'digit',
  247:                    default_value => 4,
  248:                    input_size => 2,
  249:                    comment => 'グラフ下部の目盛り部分から上に少し突き出ている線の長さ',
  250:                },
  251:                y_tick_number => {
  252:                    desc => 'Y軸目盛り個数',
  253:                    type => 'digit',
  254:                    default_value => 5,
  255:                    input_size => 2,
  256:                    comment => 'グラフ左の目盛り部分から右に少し突き出ている線の長さ',
  257:                },
  258:                y_tick_length => {
  259:                    desc => 'Y軸目盛り線長',
  260:                    shortdesc => '線長',
  261:                    type => 'digit',
  262:                    default_value => 4,
  263:                    input_size => 2,
  264:                },
  265:                x_label_skip => {
  266:                    desc => 'X軸目盛りスキップ幅',
  267:                    shortdesc => 'スキップ幅',
  268:                    type => 'digit',
  269:                    default_value => 1,
  270:                    input_size => 2,
  271:                },
  272:                x_label_offset => {
  273:                    desc => 'X軸目盛りスキップオフセット',
  274:                    shortdesc => 'スキップ開始オフセット',
  275:                    type => 'digit',
  276:                    default_value => 0,
  277:                    input_size => 2,
  278:                },
  279:                y_label_skip => {
  280:                    desc => 'Y軸目盛りスキップ幅',
  281:                    shortdesc => 'スキップ幅',
  282:                    type => 'digit',
  283:                    default_value => 1,
  284:                    input_size => 2,
  285:                },
  286:                y_label_offset => {
  287:                    desc => 'Y軸目盛りスキップオフセット',
  288:                    shortdesc => 'スキップ開始オフセット',
  289:                    type => 'digit',
  290:                    default_value => 0,
  291:                    input_size => 2,
  292:                },
  293:                x_label_position => {
  294:                    desc => 'X軸ラベル位置',
  295:                    shortdesc => '位置',
  296:                    type => 'realdigit',
  297:                    subdesc => '0〜1.0 の実数',
  298:                    default_value => '0.75',
  299:                    input_size => 5,
  300:                },
  301:                y_label_position => {
  302:                    desc => 'Y軸ラベル位置',
  303:                    shortdesc => '位置',
  304:                    type => 'realdigit',
  305:                    subdesc => '0〜1.0 の実数',
  306:                    default_value => 0.5,
  307:                    input_size => 5,
  308:                },
  309:                x_labels_vertical => {
  310:                    desc => 'X軸ラベル縦横配置',
  311:                    shortdesc => '縦横配置',
  312:                    type => 'option',
  313:                    option_values => {
  314:                        1 => {
  315:                            desc  => '縦',
  316:                        },
  317:                        0 => {
  318:                            desc  => '横',
  319:                            is_default => 1,
  320:                        },
  321:                    },
  322:                },
  323:                box_axis => {
  324:                    desc => '軸囲みタイプ',
  325:                    type => 'option',
  326:                    option_values => {
  327:                        1 => {
  328:                            desc  => '上下左右を囲む',
  329:                            is_default => 1,
  330:                        },
  331:                        0 => {
  332:                            desc  => '左と下だけ囲む',
  333:                        },
  334:                    },
  335:                },
  336:                show_values => {
  337:                    desc => '値表示',
  338:                    type => 'option',
  339:                    option_values => {
  340:                        1 => {
  341:                            desc  => 'あり',
  342:                            is_default => 1,
  343:                        },
  344:                        0 => {
  345:                            desc  => 'なし',
  346:                        },
  347:                    },
  348:                    affect => {
  349:                        0 => {
  350:                              values_vertical => 0,
  351:                              values_space    => 0,
  352:                          },
  353:                    },
  354:                    comment => 'グラフの点のそばに値を表示する。',
  355:                },
  356:                values_vertical => {
  357:                    desc => '縦横配置',
  358:                    type => 'option',
  359:                    option_values => {
  360:                        0 => {
  361:                            desc  => '横',
  362:                            is_default => 1,
  363:                        },
  364:                        1 => {
  365:                            desc  => '縦',
  366:                        },
  367:                    },
  368:                    comment => 'true の場合、グラフの点のそばの値表示を縦向きにする。',
  369:                },
  370:                values_space => {
  371:                    desc => '値スペース',
  372:                    type => 'digit',
  373:                    default_value => 4,
  374:                    input_size => 3,
  375:                    comment => 'グラフの点と、そのそばに表示する値の文字列の間隔。ピクセル単位。',
  376:                },
  377: 
  378:                no_axes => {
  379:                    desc => '軸の有無',
  380:                    type => 'option',
  381:                    option_values => {
  382:                        1 => {
  383:                            desc  => 'なし',
  384:                        },
  385:                        'undef' => {
  386:                            desc  => 'あり',
  387:                            is_default => 1,
  388:                        },
  389:                    },
  390:                    affect => {
  391:                        1 => { box_axis => 0, },
  392:                    },
  393:                    comment => 'グラフの四方を囲む枠線の有無',
  394:                },
  395:                axis_space => {
  396:                    desc => '目盛りフォント/グラフ間余白',
  397:                    type => 'digit',
  398:                    default_value => 4,
  399:                    input_size => 2,
  400:                    comment => '10・20 などの目盛りの文字列と、グラフ枠線との間隔。ピクセル数。',
  401:                },
  402:                zero_axis => {
  403:                    desc => 'Y軸ゼロ目盛り',
  404:                    shortdesc => 'ゼロ目盛り',
  405:                    type => 'option',
  406:                    option_values => {
  407:                        1 => {
  408:                            desc  => 'あり',
  409:                        },
  410:                        0 => {
  411:                            desc  => 'なし',
  412:                            is_default => 1,
  413:                        },
  414:                    },
  415:                    comment => 'Y の値が 0 である位置に線を引く。つまり Y=0 の横棒が引かれる。',
  416:                },
  417:                zero_axis_only => {
  418:                    desc => 'Y軸ゼロ目盛り*のみ*',
  419:                    shortdesc => 'ゼロ目盛りのみ',
  420:                    type => 'option',
  421:                    option_values => {
  422:                        1 => {
  423:                            desc  => 'する',
  424:                        },
  425:                        0 => {
  426:                            desc  => 'しない',
  427:                            is_default => 1,
  428:                        },
  429:                    },
  430:                    affect => {
  431:                        1 => {
  432:                            zero_axis => 0,
  433:                        },
  434:                    },
  435:                    comment => 'Y の値が 0 である位置のみに線を引く。つまり Y=0 の横棒を引き、それ以外の横棒を引かない。',
  436:                },
  437:                bgclr => {
  438:                    desc => 'bgclr(??)',
  439:                    type => 'color',
  440:                    default_value => 'pink',
  441:                    comment => 'よくわからん',
  442:                },
  443:                fgclr => {
  444:                    desc => '軸/目盛り/枠の色',
  445:                    type => 'color',
  446:                    default_value => 'black',
  447:                },
  448:                boxclr => {
  449:                    desc => 'グラフ背景色',
  450:                    type => 'color',
  451:                    default_value => 'white',
  452:                },
  453:                accentclr => {
  454:                    desc => '棒/領域/円グラフ枠色',
  455:                    type => 'color',
  456:                    default_value => 'orange',
  457:                },
  458:                axislabelclr => {
  459:                    desc => '目盛りラベル色',
  460:                    type => 'color',
  461:                    default_value => 'dblue',
  462:                },
  463:                legendclr => {
  464:                    desc => '凡例色',
  465:                    type => 'color',
  466:                    default_value => 'dblue',
  467:                },
  468: 
  469:                value_font => {
  470:                    desc => '値フォント',
  471:                    type => 'font',
  472:                    default_value => 'gdTinyFont',
  473:                },
  474:                pie_height => {
  475:                    desc => '円グラフ立体高さ',
  476:                    shortdesc => '立体高さ',
  477:                    type => 'digit',
  478:                    input_size => 2,
  479:                    default_value => 30,
  480:                },
  481:                label => {
  482:                    desc => 'ラベル',
  483:                    type => 'string',
  484:                    input_size => 12,
  485:                    default_value => 'this is label',
  486:                },
  487:                labelclr => {
  488:                    desc => 'ラベルの色',
  489:                    type => 'color',
  490:                    default_value => 'black',
  491:                },
  492:                start_angle => {
  493:                    desc => '描画開始角度',
  494:                    subdesc => '0〜360。0:真下 90:左 180:上 270:右',
  495:                    type => 'digit',
  496:                    input_size => 3,
  497:                    default_value => 0,
  498:                },
  499:                suppress_angle => {
  500:                    desc => '値描画省略角度',
  501:                    subdesc => '0〜360。データ割合が少なくてこれ以下の角度なら、値を描画しない',
  502:                    type => 'digit',
  503:                    input_size => 3,
  504:                    default_value => 0,
  505:                },
  506:                shadow_depth => {
  507:                    desc => '影の深さ',
  508:                    type => 'digit',
  509:                    input_size => 2,
  510:                    default_value => 0,
  511:                },
  512:                shadowclr    => {
  513:                    desc => '影の色',
  514:                    type => 'color',
  515:                    default_value => 'gray',
  516:                },
  517:                bar_spacing  => {
  518:                    desc => '棒グラフ間の空白',
  519:                    type => 'digit',
  520:                    input_size => 2,
  521:                    default_value => 0,
  522:                },
  523:                cumulate => {
  524:                    desc => '積算',
  525:                    type => 'option',
  526:                    option_values => {
  527:                        1 => {
  528:                            desc  => 'する',
  529:                        },
  530:                        0 => {
  531:                            desc  => 'しない',
  532:                            is_default => 1,
  533:                        },
  534:                    },
  535:                },
  536:                line_width => {
  537:                    desc => '線の太さ',
  538:                    type => 'digit',
  539:                    input_size => 2,
  540:                    default_value => 1,
  541:                },
  542:                legend_placement => {
  543:                    desc => '凡例位置',
  544:                    shortdesc => '位置',
  545:                    type => 'option',
  546:                    option_values => {
  547:                        BL => { desc => '下部左'   },
  548:                        BC => { desc => '下部中央', is_default => 1 },
  549:                        BR => { desc => '下部右'   },
  550:                        RT => { desc => '右上部'   },
  551:                        RC => { desc => '右中央'   },
  552:                        RB => { desc => '右下部'   },
  553:                    },
  554:                },
  555:                legend_spacing => {
  556:                    desc => '凡例余白',
  557:                    shortdesc => '余白',
  558:                    type => 'digit',
  559:                    input_size => 2,
  560:                    default_value => 4,
  561:                },
  562:                legend_marker_width => {
  563:                    desc => '凡例マーカー幅',
  564:                    shortdesc => 'マーカー幅',
  565:                    type => 'digit',
  566:                    input_size => 2,
  567:                    default_value => 12,
  568:                },
  569:                legend_marker_height => {
  570:                    desc => '凡例マーカー高さ',
  571:                    shortdesc => 'マーカー高さ',
  572:                    type => 'digit',
  573:                    input_size => 2,
  574:                    default_value => 8,
  575:                },
  576:                marker_size => {
  577:                    desc => 'マーカーサイズ',
  578:                    type => 'digit',
  579:                    input_size => 2,
  580:                    default_value => 4,
  581:                },
  582:                y_max_value => {
  583:                    desc => 'Y軸最大値',
  584:                    shortdesc => '最大値',
  585:                    type => 'digit',
  586:                    input_size => 5,
  587:                    default_value => 'undef',
  588:                    comment => 'Y値の最大値以上の値を指定すること (GD の仕様)',
  589: 
  590:                },
  591:                y_min_value => {
  592:                    desc => 'Y軸最小値',
  593:                    shortdesc => '最小値',
  594:                    type => 'digit',
  595:                    input_size => 5,
  596:                    default_value => 'undef',
  597:                    comment => 'Y値の最小値以下の値を指定すること (GD の仕様)',
  598:                },
  599:                x_plot_values => {
  600:                    desc => 'X軸目盛り値',
  601:                    type => 'option',
  602:                    option_values => {
  603:                        1 => {
  604:                            desc  => '描画する',
  605:                            is_default => 1,
  606:                        },
  607:                        0 => {
  608:                            desc  => '描画しない',
  609:                        },
  610:                    },
  611:                    affect => {
  612:                        0 => {
  613:                            x_long_ticks      => 0,
  614:                            x_tick_length     => 0,
  615:                            x_axis_font       => 0,
  616:                            x_ticks           => 0,
  617:                            x_label_skip      => 0,
  618:                            x_label_offset    => 0,
  619:                            x_labels_vertical => 0,
  620:                        },
  621:                    },
  622:                },
  623:                y_plot_values => {
  624:                    desc => 'Y軸目盛り値',
  625:                    type => 'option',
  626:                    option_values => {
  627:                        1 => {
  628:                            desc  => '描画する',
  629:                            is_default => 1,
  630:                        },
  631:                        0 => {
  632:                            desc  => '描画しない',
  633:                        },
  634:                    },
  635:                    affect => {
  636:                        0 => {
  637:                            y_axis_font  => 0,
  638:                        },
  639:                    },
  640:                },
  641: 
  642:                );
  643: 
  644: my ($mode, $graph_type, $ref_line_types, $ref_data, $ref_legends, %FORM) = &parse_args;
  645: 
  646: if ( $mode eq 'make_graph' ){
  647:     &make_graph(%FORM);
  648: } elsif ( $mode eq 'blank' ){
  649:     print "Content-type: text/html\n\n";
  650: } else {
  651:     &make_html();
  652: }
  653: 
  654: exit 0;
  655: 
  656: #-------------------------------------------------------
  657: sub make_html {
  658:     my $rownum = 6;
  659:     my $colnum = 3;
  660: 
  661:     my @row_list;
  662:     for ( my $row=1 ; $row<=$rownum ; $row++ ){
  663:         my @data_column_list;
  664:         for ( my $col=1 ; $col<=$colnum ; $col++ ){
  665:             my %hash;
  666:             $hash{'column_number'} = $col;
  667:             $hash{'row_number'}    = $row;
  668:             $hash{'value'}         = $col == 1 ? $row*10 : int(rand()*1000)-300;
  669:             $hash{'nouse_in_pie'}  = $col > 2 ? 1 : 0;
  670:             push(@data_column_list, \%hash);
  671:         }
  672:         push(@row_list,
  673:              {
  674:               data_column_list => \@data_column_list,
  675:              });
  676:     }
  677: 
  678:     my $tmpl_str = <<END;
  679: <html lang="ja">
  680: <head>
  681:  <meta http-equiv="Content-Type" content="text/html; charset=EUC-JP">
  682:  <meta http-equiv="Content-Script-Type" content="text/javascript">
  683:  <meta http-equiv="Content-Style-Type" content="text/css">
  684:  <title>GD::Graph グラフ作成マシーン</title>
  685:  <style type="text/css">
  686:  <!--
  687:   td, body { font-size: 80% }
  688:   input  { border: 1px solid #666666; padding: 0px; }
  689:   select { font-size: 90%; border: 1px solid #666666; padding: 0px; }
  690:   .desc { color: #993333; }
  691:   .defsform td { border-bottom: 1px solid #999999 }
  692:   .defsform tr { margin: 0px; padding: 0px; }
  693:   .defsform td, th {  font-size: 80% }
  694:   .caption { width: 100%; color: white; font-size: 120%; background-color: #4444bb; }
  695:  -->
  696:  </style>
  697: </head>
  698: <body>
  699: <table width="100%">
  700:  <tr>
  701:   <td><h1 style="font-size: 120%; margin: 0px; padding: 0px;">GD::Graph グラフ作成マシーン</h1></td>
  702:   <td align="right"><a href="../../gd-graph.html">GD::Graph によるグラフ生成 へ戻る</a></td>
  703:  </tr>
  704: </table>
  705: 
  706: <form name="gdform" method="POST" action="@{[ $ENV{'SCRIPT_NAME'} ]}"
  707:       target="graph_iframe"
  708:       onSubmit='document.getElementById("graph_iframe_id").width=(this.width.value*1)+40; document.getElementById("graph_iframe_id").height=(this.height.value*1)+40;'>
  709: 
  710:  <table width="100%" border=1 cellpadding=0 cellspacing=0>
  711:   <tr>
  712:    <td colspan="3">
  713:     @{[ &make_form_common() ]}
  714:    </td>
  715:   </tr>
  716: 
  717:   <tr valign="top">
  718:    <td>
  719:     グラフ種類
  720:     <select name="graph_type" onChange="depend_check(this); this.form.submit()">
  721:       <option value="lines">折れ線</option>
  722:       <option value="linespoints">点付き折れ線</option>
  723:       <option value="bars">縦棒グラフ</option>
  724:       <option value="hbars">横棒グラフ</option>
  725:       <option value="points">点グラフ</option>
  726:       <option value="area">折れ線領域グラフ</option>
  727:       <option value="pie">円グラフ</option>
  728:     </select>
  729: 
  730:     <table border="0" cellpadding="0" cellspacing="0" style="padding: 0px; margin: 0px;">
  731:       <tr align="center">
  732:         <th>X軸<br><nobr>項目名</nobr></th>
  733:           <TMPL_LOOP NAME="column_list">
  734:             <th>データ<TMPL_VAR NAME="column_number"></th>
  735:           </TMPL_LOOP>
  736:       </tr>
  737:       <TMPL_LOOP NAME="row_list">
  738:         <tr align="center">
  739:           <TMPL_LOOP NAME="data_column_list">
  740:             <td>
  741:               <input type="text" name="<TMPL_VAR NAME="column_number">,<TMPL_VAR NAME="row_number">" value="<TMPL_VAR NAME="value">" size=4
  742:                      <TMPL_IF NAME="nouse_in_pie">class="nouse_in_pie"</TMPL_IF>
  743:                      onChange="this.form.submit()">
  744:             </td>
  745:           </TMPL_LOOP>
  746:         </tr>
  747:       </TMPL_LOOP>
  748: 
  749:       <tr>
  750:         <th><nobr>凡例</nobr></th>
  751:         <TMPL_LOOP NAME="column_list">
  752:           <td><input type="text" name="legend<TMPL_VAR NAME="column_number">" class="nouse_in_pie" value="Legend<TMPL_VAR NAME="column_number">" size=8 onChange="this.form.submit()"></td>
  753:         </TMPL_LOOP>
  754:       </tr>
  755: 
  756:       <tr>
  757:         <th><nobr>線タイプ</nobr></th>
  758:         <TMPL_LOOP NAME="column_list">
  759:           <td>
  760:             <select name="line_type<TMPL_VAR NAME="column_number">" onChange="this.form.submit()" class="use_in_lines_linespoints">
  761:               <option value="1">実線</option>
  762:               <option value="2">破線</option>
  763:               <option value="3">点線</option>
  764:               <option value="4">鎖線</option>
  765:             </select>
  766:           </td>
  767:         </TMPL_LOOP>
  768:       </tr>
  769:     </table>
  770: 
  771:     <p>
  772:     <input type="hidden" name="mode" value="make_graph">
  773:     <input type="submit" value="グラフ作成" style="background-color: #ff9999; font-size: 130%">
  774:     <input type="button" value="リセット" onClick="this.form.reset(); all_depend_check(); this.form.submit();">
  775:     </p>
  776:    </td>
  777: 
  778:    <td rowspan="3">
  779:     @{[ &make_form('basic') ]}
  780:     @{[ &make_form('type_depend') ]}
  781:     <br>
  782: 
  783:     <iframe src="$ENV{'SCRIPT_NAME'}?mode=blank" name="graph_iframe" id="graph_iframe_id" width="440" height="240">
  784:      この部分はインラインフレームを使用しています。
  785:     </iframe>
  786:         
  787:     @{[ &make_form('bottom') ]}
  788:    </td>
  789: 
  790:    <td width="30%">
  791:        機能解説
  792:        <textarea name="messagearea" cols=30 rows=9 readonly style='border: 1px solid black; font-size: 100%'></textarea>
  793:    </td>
  794: 
  795:   </tr>
  796: 
  797:   <tr valign="top">
  798:    <td>
  799:     @{[ &make_form('left') ]}
  800:    </td>
  801: 
  802:    <td>
  803:     @{[ &make_form('right') ]}
  804:    </td>
  805:   </tr>
  806: 
  807:   <tr>
  808:    <td></td>
  809:        
  810:    <td></td>
  811:   </tr>
  812: 
  813:  </table>
  814: </form>
  815: 
  816: <script type="text/javascript">
  817: <!--
  818:     all_depend_check();
  819:     document.gdform.submit();
  820: // -->
  821: </script>
  822: 
  823: </body>
  824: </html>
  825: END
  826: ;
  827:     my $tmpl = HTML::Template->new(scalarref => \$tmpl_str);
  828:     $tmpl->param(column_list => [ map { my %h=(column_number => $_); \%h } (1..$colnum-1) ]);
  829:     $tmpl->param(row_list    => \@row_list);
  830: 
  831:     print "Content-type: text/html; charset=EUC-JP\n\n";
  832:     print $tmpl->output;
  833: }
  834: 
  835: 
  836: #-------------------------------------------------------
  837: sub make_graph {
  838:     my $graph;
  839:     if ( $graph_type eq 'lines'       ){ $graph = GD::Graph::lines       ->new($FORM{'width'}, $FORM{'height'}); }
  840:     if ( $graph_type eq 'linespoints' ){ $graph = GD::Graph::linespoints ->new($FORM{'width'}, $FORM{'height'}); }
  841:     if ( $graph_type eq 'bars'        ){ $graph = GD::Graph::bars        ->new($FORM{'width'}, $FORM{'height'}); }
  842:     if ( $graph_type eq 'hbars'       ){ $graph = GD::Graph::hbars       ->new($FORM{'width'}, $FORM{'height'}); }
  843:     if ( $graph_type eq 'points'      ){ $graph = GD::Graph::points      ->new($FORM{'width'}, $FORM{'height'}); }
  844:     if ( $graph_type eq 'area'        ){ $graph = GD::Graph::area        ->new($FORM{'width'}, $FORM{'height'}); }
  845:     if ( $graph_type eq 'pie'         ){ $graph = GD::Graph::pie         ->new($FORM{'width'}, $FORM{'height'}); }
  846: 
  847:     $graph->set( title                => $FORM{'title'},
  848:                  x_label              => $FORM{'x_label'},
  849:                  y_label              => $FORM{'y_label'},
  850:                  x_ticks              => $FORM{'x_ticks'},
  851:                  x_label_skip         => $FORM{'x_label_skip'},
  852:                  x_tick_offset        => $FORM{'x_tick_offset'},
  853:                  y_label_skip         => $FORM{'y_label_skip'},
  854:                  y_tick_offset        => $FORM{'y_tick_offset'},
  855:                  x_label_position     => $FORM{'x_label_position'},
  856:                  y_label_position     => $FORM{'y_label_position'},
  857:                  x_labels_vertical    => $FORM{'x_labels_vertical'},
  858:                  box_axis             => $FORM{'box_axis'},
  859:                  no_axes              => $FORM{'no_axes'},
  860:                  t_margin             => $FORM{'t_margin'},
  861:                  b_margin             => $FORM{'b_margin'},
  862:                  l_margin             => $FORM{'l_margin'},
  863:                  r_margin             => $FORM{'r_margin'},
  864:                  x_long_ticks         => $FORM{'x_long_ticks'},
  865:                  x_tick_length        => $FORM{'x_tick_length'},
  866: #                x_tick_number        => $FORM{'x_tick_number'},
  867: #                x_tick_number        => 'auto',
  868:                  y_long_ticks         => $FORM{'y_long_ticks'},
  869:                  y_tick_length        => $FORM{'y_tick_length'},
  870:                  y_tick_number        => $FORM{'y_tick_number'},
  871:                  bgclr                => $FORM{'bgclr'},
  872:                  fgclr                => $FORM{'fgclr'},
  873:                  boxclr               => $FORM{'boxclr'},
  874:                  accentclr            => $FORM{'accentclr'},
  875:                  axislabelclr         => $FORM{'axislabelclr'},
  876:                  legendclr            => $FORM{'legendclr'},
  877:                  axis_space           => $FORM{'axis_space'},
  878:                  pie_height           => $FORM{'pie_height'},
  879:                  start_angle          => $FORM{'start_angle'},
  880:                  suppress_angle       => $FORM{'suppress_angle'},
  881:                  shadow_depth         => $FORM{'shadow_depth'},
  882:                  shadowclr            => $FORM{'shadowclr'},
  883:                  bar_spacing          => $FORM{'bar_spacing'},
  884:                  zero_axis            => $FORM{'zero_axis'},
  885:                  zero_axis_only       => $FORM{'zero_axis_only'},
  886:                  cumulate             => $FORM{'cumulate'},
  887:                  line_width           => $FORM{'line_width'},
  888:                  line_types           => $ref_line_types,
  889:                  legend_placement     => $FORM{'legend_placement'},
  890:                  marker_size          => $FORM{'marker_size'},
  891:                  legend_spacing       => $FORM{'legend_spacing'},
  892:                  legend_marker_width  => $FORM{'legend_marker_width'},
  893:                  legend_marker_height => $FORM{'legend_marker_height'},
  894:                  y_max_value          => $FORM{'y_max_value'},
  895:                  y_min_value          => $FORM{'y_min_value'},
  896:                  x_plot_values        => $FORM{'x_plot_values'},
  897:                  y_plot_values        => $FORM{'y_plot_values'},
  898:                  values_vertical      => $FORM{'values_vertical'},
  899:                  values_space         => $FORM{'values_space'},
  900: #                y_number_format => "%04d",
  901:                  );
  902: 
  903:     if ( $graph_type eq 'pie' ){
  904:         $graph->set(
  905:                     label             => $FORM{'label'},
  906:                     labelclr          => $FORM{'labelclr'},
  907:                     );
  908:     }
  909: 
  910: 
  911: #    my $font_file ='/usr/X11R6/lib/X11/fonts/TrueType/sazanami-gothic.ttf';
  912: #       $graph->set_title_font($font_file, 18);
  913: 
  914: 
  915:     $graph->set_title_font(get_font($FORM{'title_font'}));
  916: 
  917:     # 意味のないフォントを設定すると GD が落ちることに注意。
  918:     # 例えば pie にはラベルがないので set_x_label_font をセットすると落ちる。
  919: 
  920:     if ( $graph_type eq 'pie' ){
  921:         $graph->set_value_font(get_font($FORM{'value_font'}));
  922:     } else {
  923:         $graph->set_x_label_font(get_font($FORM{'x_label_font'}));
  924:         $graph->set_y_label_font(get_font($FORM{'y_label_font'}));
  925:         $graph->set_x_axis_font(get_font($FORM{'x_axis_font'}));
  926:         $graph->set_y_axis_font(get_font($FORM{'y_axis_font'}));
  927: 
  928:         # 凡例がすべて空文字の場合は GD が落ちるので、事前チェック。
  929:         foreach my $legend ( @$ref_legends ){
  930:             if ( length($legend) > 0 ){
  931:                 $graph->set_legend(@$ref_legends);
  932:                 last;
  933:             }
  934:         }
  935:     } 
  936: 
  937:     if ( $FORM{'show_values'} ){
  938:         $graph->set(show_values => $ref_data);
  939:     }
  940:     my $image = $graph->plot($ref_data) or die "Cannot create image";
  941:     binmode STDOUT;
  942:     print "Content-type: image/png\n\n";
  943:     print $image->png();
  944: }
  945: 
  946: #------------------------------------------------------------------------------------
  947: 
  948: sub parse_args {
  949:     my $query_string;
  950:     my $l_mode = '';
  951:     my $l_graph_type = '';
  952:     my %l_FORM;
  953:     my @l_data;
  954: 
  955:     if ( $ENV{'REQUEST_METHOD'} eq 'POST') {
  956:         read(STDIN, $query_string, $ENV{CONTENT_LENGTH});
  957:     } else {
  958:         $query_string = $ENV{QUERY_STRING};
  959:     }
  960: 
  961:     my %line_type_hash;
  962:     my %data_hash;
  963:     my %legend_hash;
  964: 
  965:     foreach ( split(/&/, $query_string) ) {
  966:         my ($name, $value) = split(/=/, $_);
  967: 
  968:         $value =~ tr/+/ /;
  969:         $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg;
  970: 
  971:         # name="1,2" という渡し方をしているるので、URL デコードが必要。
  972:         $name =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C", hex($1))/eg;
  973: 
  974:         if ( $name eq 'mode' ){
  975:             $l_mode = $value;
  976:         } elsif ( $name eq 'graph_type' ){
  977:             $l_graph_type = $value;
  978:         } elsif ( $name =~ m/^line_type(\d+)$/ ){
  979:             $line_type_hash{$1} = $value;
  980:         } elsif ( $name =~ m/^(\d+),(\d+)/ ){
  981:             if ( $value eq 'undef' ){
  982:                 $data_hash{$1}{$2} = undef;
  983:             } else {
  984:                 $data_hash{$1}{$2} = $value;
  985:             }
  986:         } elsif ( $name =~ m/^legend(\d+)/ ){
  987:             $legend_hash{$1} = $value;
  988:         } else {
  989:             if ( $value eq 'undef' ){
  990:                 $l_FORM{$name} = undef;
  991:             } else {
  992:                 $l_FORM{$name} = $value;
  993:             }
  994:         }
  995:     }
  996: 
  997:     my @l_line_types = map { $_ = $line_type_hash{$_} } sort { $a<=>$b } keys %line_type_hash;
  998:     my @l_legends = map { $_ = $legend_hash{$_} } sort { $a<=>$b } keys %legend_hash;
  999:     my @l_data;
 1000:     foreach my $col (sort { $a <=> $b } keys %data_hash ){
 1001:         my @data;
 1002:         foreach my $row (sort { $a <=> $b } keys %{$data_hash{$col}} ){
 1003:             push(@data, $data_hash{$col}{$row});
 1004:         }
 1005:         push(@l_data, \@data);
 1006:     }
 1007: 
 1008:     return ($l_mode, $l_graph_type, \@l_line_types, \@l_data, \@l_legends, %l_FORM);
 1009: }
 1010: 
 1011: sub get_font {
 1012:     my ($font_str) = @_;
 1013: 
 1014:     if ( $font_str eq 'gdGiantFont'      ){ return gdLargeFont;      }
 1015:     if ( $font_str eq 'gdLargeFont'      ){ return gdLargeFont;      }
 1016:     if ( $font_str eq 'gdMediumBoldFont' ){ return gdMediumBoldFont; }
 1017:     if ( $font_str eq 'gdSmallFont'      ){ return gdSmallFont;      }
 1018:     if ( $font_str eq 'gdTinyFont'       ){ return gdTinyFont;       }
 1019: }
 1020: 
 1021: sub get_font_list {
 1022:     my @fonts = ('gdGiantFont',
 1023:                  'gdLargeFont',
 1024:                  'gdMediumBoldFont',
 1025:                  'gdSmallFont',
 1026:                  'gdTinyFont',
 1027:                  );
 1028:     return @fonts;
 1029: }
 1030: 
 1031: sub get_colorname_list {
 1032:     return GD::Graph::colour::colour_list();
 1033: }
 1034: sub get_htmlrgb_by_colorname {
 1035:     my ($colorname) = @_;
 1036:     my ($r, $g, $b) = GD::Graph::colour::_rgb($colorname);
 1037:     return sprintf("#%02x%02x%02x", $r, $g, $b);
 1038: }
 1039: 
 1040: # "#FF00BB" という文字列を渡し、補色を求める。ただしグレーの補色はグレーになるので、
 1041: # 明度差を適当に
 1042: sub get_complementary_htmlrgb {
 1043:     my ($rgb) = @_;
 1044:     my ($r, $g, $b) = $rgb =~ m/^#(..)(..)(..)/;
 1045:     my ($comp_r, $comp_g, $comp_b) = (255-hex($r), 255-hex($g), 255-hex($b));
 1046: 
 1047:     if ( abs(( $comp_r + $comp_g + $comp_b ) - ( hex($r) + hex($g) + hex($b) )) < 400 ){
 1048:         if ( $comp_r + $comp_g + $comp_b > (255*3)/2 ){
 1049:             # RGB 合計が 255段階×RGB3色の半分より大きければ、黒。
 1050:             $comp_r = $comp_g = $comp_b = 0;
 1051:         } else {
 1052:             # そうでなければ、白。
 1053:             $comp_r = $comp_g = $comp_b = 255;
 1054:         }
 1055:     }
 1056:     return sprintf("#%02x%02x%02x", $comp_r, $comp_g, $comp_b);
 1057: }
 1058: 
 1059: #------------------------------------------------------------------------------------
 1060: 
 1061: sub make_form_common {
 1062:     my @depend_info;
 1063: 
 1064:     foreach my $def (sort keys %gd_defs){
 1065:         if ( defined $gd_defs{$def}->{affect} ){
 1066:             my %hash;
 1067:             $hash{'element_name'} = $def;
 1068: 
 1069:             my @depend_info_per_element;
 1070:             foreach my $joined_conds_to_enable ( keys %{$gd_defs{$def}->{affect}} ){
 1071:                 my %hash2;
 1072:                 my @conds_to_enable;
 1073:                 foreach (split(/,/, $joined_conds_to_enable)){
 1074:                     push(@conds_to_enable, {cond_value => $_});
 1075:                 }
 1076:                 my @affected_elements;
 1077:                 foreach (keys %{$gd_defs{$def}->{affect}->{$joined_conds_to_enable}}){
 1078:                     push(@affected_elements, {affected_element_name => $_});
 1079:                 }
 1080: 
 1081:                 $hash2{'conds_to_enable'}   = \@conds_to_enable;
 1082:                 $hash2{'affected_elements'} = \@affected_elements;
 1083: 
 1084:                 push(@depend_info_per_element, \%hash2);
 1085:             }
 1086:             $hash{'depend_info_per_element'} = \@depend_info_per_element;
 1087:             push(@depend_info, \%hash);
 1088:         }
 1089:     }
 1090: 
 1091:     my $tmpl_str = <<END;
 1092: <script type="text/javascript">
 1093: <!--
 1094:     function all_depend_check(){
 1095:         var selects = document.getElementsByTagName("SELECT");
 1096:         for ( var i=0 ; i<selects.length ; i++ ){
 1097:                 depend_check(selects[i]);
 1098:         }
 1099:         var inputs = document.getElementsByTagName("INPUT");
 1100:         for ( var i=0 ; i<inputs.length ; i++ ){
 1101:                 depend_check(inputs[i]);
 1102:         }
 1103:     }
 1104:     function depend_check(element){
 1105:         var form = element.form;
 1106:         <TMPL_LOOP NAME="depend_info">
 1107:           if ( element.name == '<TMPL_VAR NAME="element_name">' ){
 1108:             <TMPL_LOOP NAME="depend_info_per_element">
 1109:               if (
 1110:                   <TMPL_LOOP NAME="conds_to_enable">
 1111:                     element.options[element.options.selectedIndex].value == '<TMPL_VAR NAME="cond_value">'
 1112:                     <TMPL_UNLESS __last__> || </TMPL_UNLESS>
 1113:                   </TMPL_LOOP>
 1114:                  )
 1115:               {
 1116:                 <TMPL_LOOP NAME="affected_elements">
 1117:                   form['<TMPL_VAR NAME="affected_element_name">'].disabled = true;
 1118:                   form['<TMPL_VAR NAME="affected_element_name">'].style.backgroundColor = '#d6d6d6';
 1119:                 </TMPL_LOOP>
 1120:               } else {
 1121:                 <TMPL_LOOP NAME="affected_elements">
 1122:                   form['<TMPL_VAR NAME="affected_element_name">'].disabled = false;
 1123:                   form['<TMPL_VAR NAME="affected_element_name">'].style.backgroundColor = 'white';
 1124:                 </TMPL_LOOP>
 1125:               }
 1126:             </TMPL_LOOP>
 1127:           }
 1128:         </TMPL_LOOP>
 1129: 
 1130:         var inputs  = document.getElementsByTagName("INPUT");
 1131:         var selects = document.getElementsByTagName("SELECT");
 1132:         for ( var i=0 ; i < (inputs.length + selects.length) ; i++ ){
 1133:             var e;
 1134:             if ( i < inputs.length ){
 1135:                 e = inputs[i];
 1136:             } else {
 1137:                 e = selects[i-inputs.length];
 1138:             }
 1139:             if ( e.className == 'nouse_in_pie' ){
 1140:                 if ( form.graph_type.value == 'pie' ){
 1141:                     e.disabled = true;
 1142:                     e.style.backgroundColor = '#d6d6d6';
 1143:                 } else {
 1144:                     e.disabled = false;
 1145:                     e.style.backgroundColor = 'white';
 1146:                 }
 1147:             } else if ( e.className == 'use_in_lines_linespoints' ){
 1148:                 if ( form.graph_type.value == 'lines' || form.graph_type.value == 'linespoints' ){
 1149:                     e.disabled = false;
 1150:                     e.style.backgroundColor = 'white';
 1151:                 } else {
 1152:                     e.disabled = true;
 1153:                     e.style.backgroundColor = '#d6d6d6';
 1154:                 }
 1155:             }
 1156:         }
 1157:     }
 1158: // -->
 1159: </script>
 1160: 
 1161: END
 1162:     ;
 1163: 
 1164:     my $tmpl = HTML::Template->new(scalarref => \$tmpl_str,
 1165:                                    loop_context_vars => 1);
 1166:     $tmpl->param(depend_info => \@depend_info);
 1167:     return $tmpl->output;
 1168: }
 1169: 
 1170: #------------------------------------------------------------------------------------------
 1171: sub make_form {
 1172:     my ($form_position) = @_;
 1173: 
 1174:     my $form = '';
 1175: 
 1176:     my %def_map = (
 1177:                    type_depend => {
 1178:                        caption => 'グラフ種類固有情報',
 1179:                        content => [
 1180:                                    [
 1181:                                     'group:円グラフ',
 1182:                                     'value_font',
 1183:                                     'pie_height',
 1184:                                     'label',
 1185:                                     'labelclr',
 1186:                                     'start_angle',
 1187:                                     'suppress_angle',
 1188:                                     'BR',
 1189:                                     ],
 1190:                                    [
 1191:                                     'group:線グラフ',
 1192:                                     'line_width',
 1193:                                     'BR',
 1194:                                     ],
 1195:                                    [
 1196:                                     'group:棒グラフ',
 1197:                                     'shadowclr',
 1198:                                     'shadow_depth',
 1199:                                     'bar_spacing',
 1200:                                     'BR',
 1201:                                     ],
 1202:                                    ],
 1203:                                    },
 1204:                    bottom => {
 1205:                        caption => 'X軸関連',
 1206:                        content => [
 1207:                                    [
 1208:                                     'group:目盛り',
 1209:                                     'axis_space',
 1210:                                     'BR',
 1211:                                     ],
 1212:                                    [
 1213:                                     'group:X軸ラベル',
 1214:                                     'x_label',
 1215:                                     'x_label_font',
 1216:                                     'x_label_position',
 1217:                                     'BR',
 1218:                                     ],
 1219:                                    [
 1220:                                     'group:X軸目盛り',
 1221:                                     'x_axis_font',
 1222:                                     'x_tick_length',
 1223:                                     'x_long_ticks',
 1224:                                     'x_ticks',
 1225:                                     'x_label_skip',
 1226:                                     'x_label_offset',
 1227:                                     'x_labels_vertical',
 1228:                                     'x_plot_values',
 1229:                                     'BR',
 1230:                                     ],
 1231:                                    ],
 1232:                                    },
 1233:                    left => {
 1234:                        caption => 'Y軸関連',
 1235:                        content => [
 1236:                                    [
 1237:                                     'group:Y軸ラベル',
 1238:                                     'y_label',
 1239:                                     'y_label_font',
 1240:                                     'y_label_position',
 1241:                                     'BR',
 1242:                                     ],
 1243:                                    [
 1244:                                     'group:Y軸目盛り',
 1245:                                     'y_axis_font',
 1246:                                     'y_tick_length',
 1247:                                     'y_long_ticks',
 1248:                                     'zero_axis',
 1249:                                     'zero_axis_only',
 1250:                                     'y_label_skip',
 1251:                                     'y_label_offset',
 1252:                                     'y_plot_values',
 1253:                                     'BR',
 1254:                                     ],
 1255:                                    [
 1256:                                     'group:Y軸値',
 1257:                                     'y_max_value',
 1258:                                     'y_min_value',
 1259:                                     ],
 1260:                                    ],
 1261:                                    },
 1262:                    basic => {
 1263:                        caption => '基本',
 1264:                        content => [
 1265:                                    [
 1266:                                     'group:画像',
 1267:                                     'width',
 1268:                                     'height',
 1269:                                     'BR',
 1270:                                     ],
 1271:                                    [
 1272:                                     'group:タイトル',
 1273:                                     'title',
 1274:                                     'title_font',
 1275:                                     'BR',
 1276:                                     ],
 1277:                                    ],
 1278:                        },
 1279: 
 1280:                    right =>  {
 1281:                        caption => 'X・Y軸共通',
 1282:                        content => [
 1283:                                    [
 1284:                                     'group:値',
 1285:                                     'show_values',
 1286:                                     'values_vertical',
 1287:                                     'values_space',
 1288:                                     'BR',
 1289:                                     ],
 1290:                                    [
 1291:                                     'group:軸',
 1292:                                     'no_axes',
 1293:                                     'box_axis',
 1294:                                     'BR',
 1295:                                     ],
 1296:                                    ['group:マージン',
 1297:                                     't_margin',
 1298:                                     'b_margin',
 1299:                                     'l_margin',
 1300:                                     'r_margin',
 1301:                                     'BR',
 1302:                                     ],
 1303:                                    [
 1304:                                     'group:色',
 1305:                                     'bgclr',
 1306:                                     'fgclr',
 1307:                                     'boxclr',
 1308:                                     'accentclr',
 1309:                                     'axislabelclr',
 1310:                                     'legendclr',
 1311:                                     'BR',
 1312:                                     ],
 1313:                                    [
 1314:                                     'group:凡例',
 1315:                                     'legend_placement',
 1316:                                     'legend_spacing',
 1317:                                     'legend_marker_width',
 1318:                                     'legend_marker_height',
 1319:                                     ],
 1320:                                    [
 1321:                                     'group:その他',
 1322:                                     'cumulate',
 1323:                                     'marker_size',
 1324:                                     'y_tick_number',
 1325:                                     ],
 1326:                                    ],
 1327:                                    },
 1328:                    );
 1329: 
 1330:     # %def_map 記述漏れ対策。
 1331:     my %defs_for_check = %gd_defs;
 1332: 
 1333:     my @current_defs = @{$def_map{$form_position}->{'content'}};
 1334:     my $caption      = $def_map{$form_position}->{'caption'};
 1335: 
 1336:     my @defs_ordered;
 1337:     foreach my $def (@current_defs){
 1338:         if ( ref($def) eq 'ARRAY' ){
 1339:             foreach my $def2 (@$def){
 1340:                 push(@defs_ordered, $def2);
 1341:                 delete $defs_for_check{$def2};
 1342:             }
 1343:         } else {
 1344:             push(@defs_ordered, $def);
 1345:             delete $defs_for_check{$def};
 1346:         }
 1347:     }
 1348: 
 1349:     # @def_map 記述漏れの定義情報を追加。
 1350:     if ( scalar(keys %defs_for_check) > 0 ){
 1351: #       push(@defs_ordered, 'group:未整理');
 1352:         foreach my $def (keys %defs_for_check){
 1353: #           push(@defs_ordered, $def);
 1354:         }
 1355:     }
 1356: 
 1357: 
 1358:     $form .= qq(<div class="caption">$caption</div><table width=100% cellspacing=0 cellpadding=0 border=0 class="defsform"><tr><td>\n);
 1359: 
 1360:     foreach my $def (@defs_ordered){
 1361:         if ( $def eq 'BR' ){
 1362:             $form .= "</td></tr><tr><td>\n";
 1363:             next;
 1364:         }
 1365:         if ( $def =~ m/^group:(.*)/ ){
 1366:             $form .= "▼$1\n";
 1367:             next;
 1368:         }
 1369:         if ( defined $gd_defs{$def}->{'depend_check_only'} && $gd_defs{$def}->{'depend_check_only'} ){
 1370:             # 依存関係チェックのみなのでスキップ
 1371:             next;
 1372:         }
 1373: 
 1374:         my $desc       = $gd_defs{$def}->{'desc'};
 1375:         my $shortdesc  = $gd_defs{$def}->{'shortdesc'};
 1376:         my $subdesc    = $gd_defs{$def}->{'subdesc'};
 1377:         my $type       = $gd_defs{$def}->{'type'};
 1378:         my $comment    = $gd_defs{$def}->{'comment'};
 1379:         my $input_name = $def;
 1380:         my $input_type;
 1381:         my $input_size = $gd_defs{$def}->{'input_size'};
 1382:         my @option_value_list;
 1383:         my @option_desc_list;
 1384:         if ( $type eq 'string' || $type eq 'digit' || $type eq 'realdigit' ){
 1385:             $input_type="TEXT";
 1386:         } elsif ( $type eq 'font' || $type eq 'option' || $type eq 'color' ){
 1387:             $input_type="SELECT";
 1388: 
 1389:             if ( $type eq 'font' ){
 1390:                 @option_value_list = &get_font_list();
 1391:                 @option_desc_list  = &get_font_list();
 1392:             } elsif ( $type eq 'option' ){
 1393:                 @option_value_list = keys %{$gd_defs{$def}->{'option_values'}};
 1394:                 foreach (@option_value_list){
 1395:                     push(@option_desc_list, $gd_defs{$def}->{'option_values'}->{$_}->{'desc'});
 1396:                 }
 1397:             } elsif ( $type eq 'color' ){
 1398:                 @option_value_list = &get_colorname_list();
 1399:                 @option_desc_list  = &get_colorname_list();
 1400:             }
 1401:         }
 1402:         my $input_default_value = defined $gd_defs{$def}->{'default_value'} ? $gd_defs{$def}->{'default_value'} : '';
 1403: 
 1404:         $form.= sprintf(qq(<nobr><span class="desc" title="%s" onMouseOver="document.gdform.messagearea.value='%s'+unescape('%%0D%%0A')+'%s';">%s</span>),
 1405:                         $def,
 1406:                         "$desc $def",
 1407:                         "$comment",
 1408:                         defined $shortdesc ? $shortdesc : $desc,
 1409:                         );
 1410:         
 1411:         if ( $input_type eq 'SELECT' ){
 1412:             $form .= qq(<select name="$input_name" onChange="depend_check(this); this.form.submit()">\n);
 1413:             for ( my $i=0 ; $i<@option_value_list ; $i++ ){
 1414:                 my $value = $option_value_list[$i];
 1415:                 my $desc  = $option_desc_list[$i];
 1416:                 my $selected_str = '';
 1417: 
 1418:                 if ( $gd_defs{$def}->{'option_values'}->{$value}->{'is_default'} ||
 1419:                      $value eq $gd_defs{$def}->{'default_value'} ){
 1420:                     $selected_str = 'SELECTED';
 1421:                 }
 1422:                 if ( $type eq 'color' ){
 1423:                     $form .= sprintf("  <option value='$value' $selected_str style='background-color: %s; color: %s'>$desc</option>\n",
 1424:                                      get_htmlrgb_by_colorname($value),
 1425:                                      get_complementary_htmlrgb(get_htmlrgb_by_colorname($value)));
 1426:                 } else {
 1427:                     $form .= "  <option value='$value' $selected_str>$desc</option>\n";
 1428:                 }
 1429:             }
 1430:             $form .= qq(</select>\n);
 1431:         } else {
 1432:             $form .= sprintf(qq(<input type="%s" name="%s" value="%s" %s onChange="this.form.submit()">\n),
 1433:                              $input_type,
 1434:                              $input_name,
 1435:                              $input_default_value,
 1436:                              defined $input_size ? "size='$input_size'" : '');
 1437:         }
 1438:         $form .= qq(</nobr>\n);
 1439: 
 1440:         if ( defined $subdesc ){
 1441:             $form .= qq(<span style="font-size: 80%">($subdesc)</span>\n);
 1442:         }
 1443:     }
 1444: 
 1445:     $form .= qq(</td></tr></table>\n);
 1446: 
 1447:     return $form;
 1448: }

前へ << 画像生成 全文検索 >> 次へ

$Id: gd-graph.html,v 1.3 2007/06/21 17:49:09 68user Exp $