Flower.c

// flower.c

// Copyright (c) 2005 BenBear

// Flower 0.2

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2, or (at
// your option) any later version.

// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with GNU Emacs; see the file COPYING.  If not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
// Boston, MA 02111-1307, USA.


// This program needs GTK+ 2.0.


#include <gtk/gtk.h>
#include <math.h>

#ifndef M_PI
#  define M_PI 3.1415926535898
#endif

GtkWidget *big;            // a widget for big circle
GtkWidget *small;        // a widget for small circle
GtkWidget *pen;            // position of the pen

GtkWidget *outer;        // check if small out big
GtkWidget *fill;        // check if fill all drawarea

GtkWidget *drawarea;        // the client will drawing


// "value-changed" event of the big circle, small circle and pen
void value_changed (GtkSpinButton *spinbutton,
            gpointer data)
{
  GdkRectangle rect;
  rect.x = 0;
  rect.y = 0;
  rect.width = drawarea->allocation.width;
  rect.height = drawarea->allocation.height;

  gdk_window_invalidate_rect (drawarea->window,
                  &rect, FALSE);
}

// "toggled" event of the outer and fill
void toggled (GtkToggleButton *toggle,
          gpointer data)
{
  GdkRectangle rect;
  rect.x = 0;
  rect.y = 0;
  rect.width = drawarea->allocation.width;
  rect.height = drawarea->allocation.height;

  gdk_window_invalidate_rect (drawarea->window,
                  &rect, FALSE);
}


GtkWidget *create_adjustment_entry(float cur, float min, float max)
{
  GtkAdjustment *adj;
  GtkWidget *entry;

  adj = (GtkAdjustment *)gtk_adjustment_new (cur, min, max,
                         1.0, 5.0, 0.0);
  entry = gtk_spin_button_new (adj, 0, 0);

  g_signal_connect (G_OBJECT (entry), "value-changed",
            G_CALLBACK (value_changed), entry);

  gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (entry), FALSE);

  return entry;
}

void show_adjustment_entry (GtkWidget *entry, const char *str,
                GtkWidget *vbox)
{
  GtkWidget *label;
  GtkWidget *hbox;
 
  label = gtk_label_new (str);
  hbox = gtk_hbox_new (TRUE, 0);

  gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
 
  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);

  gtk_widget_show (label);
  gtk_widget_show (entry);
  gtk_widget_show (hbox);
}


// redraw event of drawing area
// draw the flower
gboolean
expose_event_callback (GtkWidget *widget,
               GdkEventExpose *event,
               gpointer data)
{
  int b, s, p;            // big, small and pen
  int ns;            // -small or small
  int w, h, x, y;        // width and height
  int d;
  int a, f;            // outer and fill
  double t;
 
  GdkGC *gc;
  GdkDrawable *canvas;
  GdkColor color;

  b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(big));
  s = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(small));
  p = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(pen));

  canvas = widget->window;
  gc = widget->style->fg_gc[GTK_WIDGET_STATE(widget)];
  w = widget->allocation.width;
  h = widget->allocation.height;

  a = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (outer));
  f = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (fill));

  if (f)
    {
      // zoom
      double r, m;
      m = ((w < h) ? w : h) / 2 - 2;
      r = (a ? (b + s + p)
       : ((b < s) ? (s - b + p) : (b - s + p)));
      if (r == 0)
    f = 0;            // if r == 0, then need not zoom
      t = m / r;
    }
  if (f == 0)
    {
      t = 1.0;
    }

  ns = a ? s : -s;


  //gdk_gc_offset (gc, 0, 0);
  gdk_draw_rectangle (canvas, gc, TRUE, 0, 0, w, h);

  color.red = 65535;
  color.green = 65535;
  color.blue = 65535;
  gdk_gc_set_rgb_fg_color (gc, &color);


  //
  x = w / 2 + (int)((b + ns + p) * t);
  y = h / 2;
  for (d = 1; (d % 360 != 0) || (d / 360 * b % s != 0); ++d)
    {
      double dp, xp, yp, x1, y1;
      int xx, yy;
      dp = M_PI * d / 180 * b / -ns;
      xp = b + ns + p * cos(dp);
      yp = p * sin(dp);
      x1 = xp * cos(-M_PI * d / 180) - yp * sin(-M_PI * d / 180);
      y1 = xp * sin(-M_PI * d / 180) + yp * cos(-M_PI * d / 180);
      xx = w / 2 + (int)(x1 * t);
      yy = h / 2 - (int)(y1 * t);
      gdk_draw_line (canvas, gc, x, y, xx, yy);
      x = xx;
      y = yy;
    }

  gdk_draw_line (canvas, gc, x, y,
         w / 2 + (int)((b + ns + p) * t),
         h / 2);

  color.red = 0;
  color.green = 0;
  color.blue = 0;
  gdk_gc_set_rgb_fg_color (gc, &color);

  return TRUE;
}

int main (int argc, char *argv[])
{
  GtkWidget *window;

  GtkWidget *vbox;
  GtkWidget *hbox;
  GtkWidget *align;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_container_set_border_width (GTK_CONTAINER (window), 5);
  gtk_window_set_title (GTK_WINDOW (window), "Flower");

  g_signal_connect (G_OBJECT (window), "destroy",
            G_CALLBACK (gtk_main_quit), 0);
  g_signal_connect_swapped (G_OBJECT (window), "delete_event",
                G_CALLBACK (gtk_widget_destroy),
                window);

  vbox = gtk_vbox_new (FALSE, 0);


  // create big circle
  big = create_adjustment_entry (100, 1.0, 1000.0);
  show_adjustment_entry (big, "big  ", vbox);


  // create small circle
  small = create_adjustment_entry (60, 1.0, 1000.0);
  show_adjustment_entry (small, "small", vbox);


  // create pen
  pen = create_adjustment_entry (40, 0.0, 1000.0);
  show_adjustment_entry (pen, "pen  ", vbox);


  // create check outer
  outer = gtk_toggle_button_new_with_label ("small outer of big");
  gtk_box_pack_start (GTK_BOX (vbox), outer, TRUE, TRUE, 5);
  g_signal_connect (G_OBJECT (outer), "toggled",
            G_CALLBACK (toggled), outer);
  gtk_widget_show (outer);


  // create check fill
  fill = gtk_toggle_button_new_with_label ("auto zoom");
  gtk_box_pack_start (GTK_BOX (vbox), fill, TRUE, TRUE, 0);
  g_signal_connect (G_OBJECT (fill), "toggled",
            G_CALLBACK (toggled), fill);
  gtk_widget_show (fill);

  align = gtk_alignment_new (1.0, 0.0, 0.0, 0.0);
  gtk_container_add (GTK_CONTAINER (align), vbox);


  drawarea = gtk_drawing_area_new ();
  gtk_widget_set_size_request (drawarea, 200, 200);
  g_signal_connect (G_OBJECT (drawarea), "expose_event",
            G_CALLBACK (expose_event_callback), NULL);
 
  hbox = gtk_hbox_new (FALSE, 10);
  gtk_box_pack_start (GTK_BOX (hbox), drawarea, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (hbox), align, FALSE, FALSE, 0);


  gtk_container_add (GTK_CONTAINER (window), hbox);

  gtk_widget_show (drawarea);
  gtk_widget_show (vbox);
  gtk_widget_show (align);
  gtk_widget_show (hbox);
  gtk_widget_show (window);

  gtk_main ();

  return 0;
}


下面是 Makefile:

# Makefile for Flower

flower: flower.c
    gcc flower.c -o flower `pkg-config --cflags --libs gtk+-2.0`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值