Commit 6d749c5b by PotatoGim

wxPerl을 이용해서 구현된 MVC 모델의 예

parent d0076a8f
#!/usr/bin/env perl
#=============================================================================
# FILE: mvc.pl
# USAGE: ./mvc.pl
# OPTIONS:
# BRIEF:
# AUTHOR: Ji-Hyeon Gim <potatogim@potatogim.net>
# ORGANIZATION:
# DATE: 2015년 08월 23일 16시 05분 49초
# VERSION: 1.0
# LICENSE: Artistic License 2.0
# NOTE:
#=============================================================================
use strict;
use warnings;
use utf8;
# An example of trivial wxPerl application using a Model-View-Controller
# architecture.
# Copyright 2014 Johan Vromans. All rights reservered.
# License: Artistic.
package Publisher;
# Trivial Publish/Subscribe handler.
my %subs;
sub send_message
{
my ($self, $tag, $param) = @_;
next unless $subs{$tag};
foreach (@{$subs{$tag}})
{
eval { $_->($tag, $param); };
}
}
sub subscribe
{
my ($self, $sub, $tag) = @_;
$subs{$tag} //= [];
push(@{$subs{$tag}}, $sub);
}
package Model;
# This is where the money^Wdata and logic is.
# Nothing GUI oriented here.
sub new
{
my ($pkg) = @_;
my $self = bless { money => 0 }, $pkg;
return $self;
}
sub inc_money
{
my ($self, $value) = @_;
$self->{money} += $value;
# Now tell anyone who cares that the value has been changed.
Publisher->send_message("MONEY CHANGED", $self->{money});
}
sub dec_money
{
my ($self, $value) = @_;
$self->{money} -= $value;
# Now tell anyone who cares that the value has been changed.
Publisher->send_message("MONEY CHANGED", $self->{money});
}
package View;
# A GUI element - - a window (Wx::Frame) that shows the current value.
use Wx qw/:window :sizer/;
use base qw/Wx::Frame/;
sub new
{
my ($pkg, $parent) = @_;
my $self = $pkg->SUPER::new($parent, -1, "Main View");
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
my $text = Wx::StaticText->new($self, -1, "My Money");
my $ctrl = Wx::TextCtrl->new($self, -1, "");
$sizer->Add($text, 0, wxEXPAND|wxALL);
$sizer->Add($ctrl, 0, wxEXPAND|wxALL);
$self->{moneyCtrl} = $ctrl;
$ctrl->SetEditable(0);
$self->SetSizer($sizer);
return $self;
}
sub set_money
{
my ($self, $money) = @_;
$self->{moneyCtrl}->SetValue($money);
}
package ChangerWidget;
# A GUI element - - a window (Wx::Frame) that allows changing the value.
use Wx qw/:window :sizer/;
use base qw/Wx::Frame/;
sub new
{
my ($pkg, $parent) = @_;
my $self = $pkg->SUPER::new($parent, -1, "Main View");
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
$self->{inc} = Wx::Button->new($self, -1, "Increase Money");
$self->{dec} = Wx::Button->new($self, -1, "Decrease Money");
$sizer->Add($self->{inc}, 0, wxEXPAND|wxALL);
$sizer->Add($self->{dec}, 0, wxEXPAND|wxALL);
$self->SetSizer($sizer);
return $self;
}
sub register
{
my ($self, $op, $code) = @_;
Wx::Event::EVT_BUTTON($self, $self->{$op}->GetId, $code);
}
package Controller;
# This is the controller.
# Nothing GUI oriented here.
# No business logic, just connecting things.
sub new
{
my ($pkg, $app) = @_;
my $self = bless {}, $pkg;
$self->{model} = Model->new;
$self->{view} = View->new;
# Set up the first frame which displays the current Model value.
$self->{view}->set_money($self->{model}->{money});
# Set up the second frame which allows the user to modify the Model's
# value.
my $changer = ChangerWidget->new($self->{view});
# Register our functions to ChangerWidget operations.
$changer->register("inc", sub { $self->inc_money; });
$changer->register("dec", sub { $self->dec_money; });
# Subscribe to all "MONEY CHANGED" messages from the Model to subscribe to
# ALL messages (topics), omit the second argument below.
Publisher->subscribe(sub { $self->money_changed(@_); }, "MONEY CHANGED");
$self->{view}->Show(1);
$changer->Show(1);
return $self;
}
sub inc_money
{
my ($self, $evt) = @_;
$self->{model}->inc_money(10);
}
sub dec_money
{
my ($self, $evt) = @_;
$self->{model}->dec_money(10);
}
sub money_changed
{
my ($self, $tag, $data) = @_;
# This method is the handler for "MONEY CHANGED" messages,
# which Publisher will call as messages are sent from the model.
#
# We already know the topic is "MONEY CHANGED", but if we didn't, $tag
# would tell us.
$self->{view}->set_money($data);
}
package main;
# The main program, Fairly standard.
no warnings qw/redefine once/;
local *Wx::App::OnInit = sub { 1; };
my $app = Wx::App->new();
Controller->new($app);
$app->MainLoop();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment