|
|
srcdir = .
builddir = /cygdrive/d/projects/debug/jlife
#ressrc1 = Generic.rc
#ressrc = $(addprefix $(srcdir)/,$(ressrc1))
#
#resobj1 = $(subst .rc,.o,$(ressrc1))
#resobj = $(addprefix $(builddir)/,$(resobj1))
src1 = $(wildcard *.cpp)
src = $(addprefix $(srcdir)/,$(src1))
objs1 = $(subst .cpp,.o,$(src1))
objs = $(addprefix $(builddir)/,$(objs1))
deps1 = $(subst .cpp,.d,$(src1))
deps = $(addprefix $(builddir)/,$(deps1))
exec = jlife.exe
incl-dirs = -I d:/projects/include
#---------------
#-- tools
RESCOMP = windres
CXX = g++
#---------------
#-- compiler switches
#CPPFLAGS = -mno-cygwin -mwindows -g
CPPFLAGS = -mno-cygwin -g -Wall -MD
#---------------
#-- MS libs required
#LIBS_MS = -lrpcrt4 -lwinmm -lshell32 -lcomctl32 -lcomdlg32 -lctl3d32 -ladvapi32 -lkernel32 -luser32
LIBS_MS = -lgdi32
#---------------
#-- final set of libs
LIBS = $(LIBS_MS)
#---------------
#-- linker switches
# -s : strip debug info
LDFLAGS = -mwindows -mno-cygwin
#---------------
#-- RC COMPILER SWITCHES
#RC_INCLUDES = --include-dir $(srcdir) --include-dir $(WX_INCLUDE)
#RC_FLAGS = --define __WXMSW__ $(RC_INCLUDES) $(DLLFLAG_rc)
RC_INCLUDES =
RC_FLAGS =
#----------------------------------------------------------------------------------------
#-- Main dependencies!
.PHONY: all clean
all: $(builddir) $(exec)
#---------------
#-- Target: executable
$(exec) : $(objs)
$(info ---Linking...)
g++ $(LDFLAGS) $^ $(LIBS) -o $@
#---------------
#-- Target: clean
clean :
-rm -rf $(builddir)
-rm *.o
-rm *.d
-rm *.exe
#-- build dir
$(builddir) :
$(info ---Creating build directory...)
if [ ! -d $(builddir) ]; then mkdir -p $(builddir); fi
include $(wildcard $(builddir)/*.d)
#-- source files
$(objs): $(builddir)/%.o:$(srcdir)/%.cpp
$(info ---Build source file...)
g++ $(incl-dirs) -c $(CPPFLAGS) $(srcdir)/$< -o $@
#-- resource file
$(resobj) : $(builddir)/%.o:$(srcdir)/%.rc
$(info ---Build resource file...)
$(RESCOMP) -i$< -o$@ $(RC_FLAGS)
|
|
|
#include "App.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>
int main(int argc, char** argv)
{
srand(time(0));
App app(std::cout);
app.Run(argc, argv);
return app.ReturnCode();
}
|
|
|
#include "Animal.h"
#include "jColor.h"
#include "EnvironmentInfo.h"
#include <stdlib.h>
static jColor WHITE(255, 255, 255);
static jColor ANIMAL1_2(16, 78, 139);
static jColor ANIMAL1_1(28, 134, 238);
static jColor ANIMAL1_0(165, 210, 245);
static jColor ANIMAL1_BABY(187, 255, 255);
//the master from which all Animals are copied... unless there's genetic crossover and mutation.
Animal gMasterAnimal;
Animal::Animal()
{
Init();
}
void Animal::Init()
{
Type = 0;
Energy = 0;
Age = 0;
YoungThreshold = 50; //this age and below is "young"
OldThreshold = 200; //this age and above is "old"
EnergyLossPerDay = 2; //the amount of energy Animal1 loses per day
PercentageEnergyLossYoung = 0.00010; //additional energy loss due to youth
PercentageEnergyLossOld = 0.00260; //additional energy loss due to old age
PlantsEatenPerDay = 6; //the amount of plants Animal1 eats
EnergyGainedByEatingPlants = 4; //the amount of energy Animal1 gets by eating plants
ExistsPercentage = 50; //the percentage of time an Animal1 is initially created
EnergyToMove = 6; //the amount of energy to move closer to food
ParentEnergyThreshold = 150; //how much energy Animal1 needs to be a parent
ChildMinimumEnergy = 50; //the minimum amount of energy Animal1 children get when they are born
ChildPercentageAdditionalEnergy = 0.15; //additional energy they get from the parents.
//set this to 100 to show that socialable is anti-survival!
//set this to 0 to show a voracious, eating machine.
Sociability = 0; //on sociable the animal is 0..100, 0 is unsociable, 100 is "clingy"
}
Animal& Animal::operator=(const Animal& other)
{
Type = other.Type;
Energy = other.Energy;
Age = other.Age;
YoungThreshold = other.YoungThreshold;
OldThreshold = other.OldThreshold; //this age and above is "old"
EnergyLossPerDay = other.EnergyLossPerDay; //the amount of energy Animal1 loses per day
PercentageEnergyLossYoung = other.PercentageEnergyLossYoung; //additional energy loss due to youth
PercentageEnergyLossOld = other.PercentageEnergyLossOld; //additional energy loss due to old age
PlantsEatenPerDay = other.PlantsEatenPerDay; //the amount of plants Animal1 eats
EnergyGainedByEatingPlants = other.EnergyGainedByEatingPlants; //the amount of energy Animal1 gets by eating plants
ExistsPercentage = other.ExistsPercentage; //the percentage of time an Animal1 is initially created
EnergyToMove = other.EnergyToMove; //the amount of energy it costs to move an Animal1
ParentEnergyThreshold = other.ParentEnergyThreshold; //how much energy Animal1 needs to be a parent
ChildMinimumEnergy = other.ChildMinimumEnergy; //the minimum amount of energy Animal1 children get when they are born
ChildPercentageAdditionalEnergy = other.ChildPercentageAdditionalEnergy; //additional energy they get from the parents.
Sociability = other.Sociability;
return *this;
}
void Animal::SetInitial(const Animal& master)
{
this->operator =(master);
int exists = rand() % 100;
if (exists < ExistsPercentage)
{
Energy = (rand() % 100) + 1;
Age = (rand() % 600) + 1;
Type = 1;
}
}
bool Animal::Exists() const
{
return Energy > 0;
}
void Animal::KillIt()
{
Type = 0;
Energy = 0;
Age = 0;
}
void Animal::Update(int& currentPlantLife)
{
//animal ages every day
Age++;
if (currentPlantLife >= PlantsEatenPerDay)
{
//there are enough plants to eat...
currentPlantLife -= PlantsEatenPerDay;
Energy += EnergyGainedByEatingPlants;
}
//animal loses energy every day
Energy -= EnergyLossPerDay;
//young animals lose more energy
if (Age < YoungThreshold)
{
//lose more energy the younger you are...
Energy -= (int) ((YoungThreshold - Age) * Energy * PercentageEnergyLossYoung);
}
//old animals lose more energy
if (Age > OldThreshold)
{
//lose more energy the older you are...
Energy -= (int) ((Age - OldThreshold) * Energy * PercentageEnergyLossOld);
}
//if the animal has no energy, it's dead
if (!Exists())
{
KillIt();
}
}
jColor Animal::GetColor() const
{
if (Age < 10)
return ANIMAL1_BABY;
if (Energy > 66)
return ANIMAL1_2;
if (Energy > 33)
return ANIMAL1_1;
if (Energy > 0)
return ANIMAL1_0;
//it's dead
return WHITE;
}
//if occupied
bool Animal::IsHigherThenSet(int& energy)
{
if (Energy > energy)
{
energy = Energy;
return true;
}
return false;
}
bool Animal::IsSociable() const
{
int dice = rand() % 100;
return (Sociability > dice) && (Energy >= EnergyToMove);
}
//move if: not enough plantlife and there's enough energy to move
bool Animal::NotEnoughFood(int currentPlantLife) const
{
return (currentPlantLife < PlantsEatenPerDay) && (Energy >= EnergyToMove);
}
void Animal::Move(Animal& from)
{
if (from.Energy < from.EnergyToMove)
return; //not enough energy to move
//a move is a copy from the original spot...
this->operator =(from);
//remove a bit of energy...
Energy -= EnergyToMove;
if (!Exists())
KillIt();
//and remove it from the previous cell
from.KillIt();
}
//both parents have to have enough energy to have a child
bool Animal::CanBeBorn(int parent1energy, int parent2energy) const
{
bool b = parent1energy >= ParentEnergyThreshold && parent2energy >= ParentEnergyThreshold;
//std::cout << "CanBeBorn: " << b << std::endl;
return b;
}
bool changeit(int& item)
{
int dice = rand() % 100;
if (dice > 98)
{
item++;
return true;
}
if (dice < 2)
{
item--;
return true;
}
return false;
}
bool changeit(double& item)
{
int dice = rand() % 100;
if (dice > 98)
{
item += 0.0001;
return true;
}
if (dice < 2)
{
item -= 0.0001;
return true;
}
return false;
}
// - the child's energy is a minimum value + a random extra value, depending on parent's energy
void Animal::BeBorn(const Animal& parent1, const Animal& parent2)
{
if (!gEnvironment.UseGenetics)
{
//copy current settings from master animal
this->operator=(gMasterAnimal);
}
//arbitrarily choose parent1 here
//if genetics are in use, it will be overwritten
//otherwise, both parents have the same type anyway
Type = parent1.Type;
//max energy the child gets is a percentage from each of the parents
double max = ChildPercentageAdditionalEnergy * parent1.Energy;
max += ChildPercentageAdditionalEnergy * parent2.Energy;
Energy = ChildMinimumEnergy;
Energy += rand() % (int) max; //ranges from 0..max
//we all start so young...
Age = 1;
//since the animal has energy and a non-zero age,
// it is officially born at this point
if (gEnvironment.UseGenetics)
{
//handle crossover from either parents items
Crossover(parent1, parent2);
//handle mutations
Mutate(parent1, parent2);
}
}
// the child's energy will be subtracted from each of the parents
void Animal::AdjustParentForBirthOf(const Animal& child)
{
//there is no female and male, so each gives up their energy equally
Energy -= child.Energy / 2;
if (!Exists())
KillIt(); //died in childbirth
}
void Animal::Crossover(const Animal& parent1, const Animal& parent2)
{
int dice;
dice = rand() % 100;
YoungThreshold = dice > 50 ? parent1.YoungThreshold : parent2.YoungThreshold;
dice = rand() % 100;
OldThreshold = dice > 50 ? parent1.OldThreshold : parent2.OldThreshold;
dice = rand() % 100;
EnergyLossPerDay = dice > 50 ? parent1.EnergyLossPerDay : parent2.EnergyLossPerDay;
dice = rand() % 100;
PercentageEnergyLossYoung = dice > 50 ? parent1.PercentageEnergyLossYoung
: parent2.PercentageEnergyLossYoung;
dice = rand() % 100;
PercentageEnergyLossOld = dice > 50 ? parent1.PercentageEnergyLossOld
: parent2.PercentageEnergyLossOld;
dice = rand() % 100;
PlantsEatenPerDay = dice > 50 ? parent1.PlantsEatenPerDay : parent2.PlantsEatenPerDay;
dice = rand() % 100;
EnergyGainedByEatingPlants = dice > 50 ? parent1.EnergyGainedByEatingPlants
: parent2.EnergyGainedByEatingPlants;
dice = rand() % 100;
ExistsPercentage = dice > 50 ? parent1.ExistsPercentage : parent2.ExistsPercentage;
dice = rand() % 100;
EnergyToMove = dice > 50 ? parent1.EnergyToMove : parent2.EnergyToMove;
dice = rand() % 100;
ParentEnergyThreshold = dice > 50 ? parent1.ParentEnergyThreshold : parent2.ParentEnergyThreshold;
dice = rand() % 100;
ChildMinimumEnergy = dice > 50 ? parent1.ChildMinimumEnergy : parent2.ChildMinimumEnergy;
dice = rand() % 100;
ChildPercentageAdditionalEnergy = dice > 50 ? parent1.ChildPercentageAdditionalEnergy
: parent2.ChildPercentageAdditionalEnergy;
}
void Animal::Mutate(const Animal& parent1, const Animal& parent2)
{
bool mutation = false;
mutation |= changeit(YoungThreshold);
mutation |= changeit(OldThreshold);
mutation |= changeit(EnergyLossPerDay);
mutation |= changeit(PercentageEnergyLossYoung);
mutation |= changeit(PercentageEnergyLossOld);
mutation |= changeit(PlantsEatenPerDay);
mutation |= changeit(EnergyGainedByEatingPlants);
//ExistsPercentage
mutation |= changeit(EnergyToMove);
mutation |= changeit(ParentEnergyThreshold);
mutation |= changeit(ChildMinimumEnergy);
mutation |= changeit(ChildPercentageAdditionalEnergy);
if (mutation)
{
Type = parent1.Type + 1;
}
else
{
Type = parent1.Type; //todo: use Parent's type
}
}
|
|
|
#ifndef ANIMAL_H_
#define ANIMAL_H_
#include "jColor.h"
class Animal
{
public:
Animal();
inline int GetType()
{
return Type;
}
void Init();
void SetInitial(const Animal& master);
void Update(int& currentPlantLife);
bool CanBeBorn(int parent1energy, int parent2energy) const;
bool Exists() const;
jColor Animal::GetColor() const;
bool IsHigherThenSet(int& energy);
bool NotEnoughFood(int currentPlantLife) const;
void Move(Animal& from);
bool IsSociable() const;
void BeBorn(const Animal& parent1, const Animal& parent2);
void AdjustParentForBirthOf(const Animal& child);
Animal& operator=(const Animal& other);
private:
void KillIt();
void Crossover(const Animal& parent1, const Animal& parent2);
void Mutate(const Animal& parent1, const Animal& parent2);
int Type;
int Energy;
int Age;
public:
int EnergyToMove;
int PlantsEatenPerDay;
int EnergyGainedByEatingPlants;
int EnergyLossPerDay;
int ExistsPercentage;
int YoungThreshold;
int OldThreshold;
double PercentageEnergyLossYoung;
double PercentageEnergyLossOld;
int ParentEnergyThreshold;
int ChildMinimumEnergy;
double ChildPercentageAdditionalEnergy;
int Sociability;
};
extern Animal gMasterAnimal;
#endif /*ANIMALINFO_H_*/
|
|
|
#include "App.h"
#include "jFunctor.h"
#include "Grid.h"
#include "GridInfo.h"
#include "EnvironmentInfo.h"
#include "jRect.h"
#include "jDialog.h"
//#include "jGDIResourceLeak.h"
#include <string>
#include <iostream>
static const int cRc_OK = 0;
static const int cRc_BadArgument = 1;
static const int cRc_CompareFailed = 2;
static Grid grid;
App::App(std::ostream& os) :
mOstream(os)
{
mStopProcessing = false;
mRc = cRc_OK;
mGeneration = 0;
}
App::~App(void)
{
}
int App::ReturnCode()
{
return mRc;
}
int App::OnMenuExit(const std::string& name)
{
std::cout << "OnMenuExit name=" << name << std::endl;
mWin.Close();
return 0;
}
//int App::OnMenuSave(const std::string& name)
// {
// std::cout << "OnMenuSave name=" << name << std::endl;
// return 0;
// }
int App::OnSettingsDone(const std::string& name)
{
std::cout << "OnSettingsDone name=" << name << std::endl;
if (name == "Ok")
{
mDlg.Close(0);
mWin.Redraw(); //redraw the screen
}
else if (name == "Cancel")
{
mDlg.Close(1);
}
mWin.SetActive();
return 0;
}
int App::OnMenuSettings(const std::string& name)
{
std::cout << "OnMenuSettings name=" << name << std::endl;
//todo: do settings dialog
jRect rct;
rct.x = 100;
rct.y = 100;
rct.width = 200;
rct.height = 150;
mDlg.Create(mWin.getWin(), "jLife - Settings...", rct);
EnvironmentInfo tmpenv = gEnvironment;
Animal tmpanimal = gMasterAnimal;
// label field, x, y, lblw, entrywidth, height
int gap = 5;
int lblx = gap + gap;
int lblwidth = 90;
int editwidth = 20;
int height = 10;
int y = 10;
mDlg.AddLabel("Sunshine%", lblx, y, lblwidth, height);
mDlg.AddEdit(tmpenv.SunPercentage, tmpenv.SunPercentage, lblx + lblwidth + gap, y, editwidth, height);
y += height + gap;
mDlg.AddLabel("Plant Life w/ Dirt", lblx, y, lblwidth, height);
mDlg.AddEdit(tmpenv.PlantLifeIncWithDirt, tmpenv.PlantLifeIncWithDirt, lblx + lblwidth + gap, y, editwidth, height);
y += height + gap;
mDlg.AddLabel("Plant Life w/out Dirt", lblx, y, lblwidth, height);
mDlg.AddEdit(tmpenv.PlantLifeIncWithoutDirt, tmpenv.PlantLifeIncWithoutDirt, lblx + lblwidth + gap, y, editwidth, height);
y += height + gap;
mDlg.AddLabel("Plant Life w/out Sun", lblx, y, lblwidth, height);
mDlg.AddEdit(tmpenv.PlantLifeDecWithoutSunshine, tmpenv.PlantLifeDecWithoutSunshine, lblx + lblwidth + gap, y, editwidth, height);
y += height + gap;
mDlg.AddLabel("Use Genetics", lblx, y, lblwidth, height);
mDlg.AddEdit((int)tmpenv.UseGenetics, (int&) tmpenv.UseGenetics, lblx + lblwidth + gap, y, editwidth, height);
y += height + gap;
mDlg.AddLabel("Sociability", lblx, y, lblwidth, height);
mDlg.AddEdit(tmpanimal.Sociability, tmpanimal.Sociability, lblx + lblwidth + gap, y, editwidth, height);
DialogCallBack cmd(this, &App::OnSettingsDone);
int buttonwidth = 40;
// y += height + gap;
// mDlg.AddButton("Help", cmd, lblx, y, buttonwidth, height);
y += height + gap;
mDlg.AddButton("Ok", cmd, lblx, y, buttonwidth, height);
mDlg.AddButton("Cancel", cmd, lblx + buttonwidth + gap, y, buttonwidth, height);
unsigned long rc = mDlg.Show(); //defaults Modal
//std::cout << "x=App tmp=" << tmp << " tmp2=" << tmp2 << std::endl;
if (rc == 0)
{
gEnvironment = tmpenv;
gMasterAnimal = tmpanimal;
}
return 0;
}
int App::OnMenuReInit(const std::string& name)
{
std::cout << "OnMenuReInit name=" << name << std::endl;
grid.ReInit();
mWin.Redraw();
return 0;
}
int App::OnMenuGoStop(const std::string& name)
{
std::cout << "OnMenuGoStop name=" << name << std::endl;
if (name == "Go!")
{
mSettingId->SetEnabled(false);
mWin.PostEvent(1, 22, 33);
mGoStopId->SetMenuItemText("Stop!");
mCalcThread->Unfreeze();
}
else
{
mSettingId->SetEnabled(true);
mGoStopId->SetMenuItemText("Go!");
mWin.PostEvent(1, 0, 0);
mCalcThread->Freeze();
}
return 0;
}
enum
{
MYEVENT = 42
};
int App::OnMyEvent(unsigned int p1)
{
//std::cout << "OnMyEvent p1=" << p1 << std::endl;
mGeneration++;
mWin.Redraw();
return 0;
}
int App::OnPaint(jGraphics& g)
{
grid.Paint(g, mGeneration);
return 0;
}
void App::Run(int argc, char** argv)
{
ProcessCommandLine(argc, argv);
if (mStopProcessing)
return;
grid.Init();
mWin.Create();
mWin.Text("jLife - new game of Life");
//create menu system
jMenu mMenu = mWin.AddMenu();
mMenu.CreateDropDown("File");
// MenuCallBack cmd1(this, &App::OnMenuSave);
// mMenu.AddItem("Save", cmd1);
MenuCallBack cmd2(this, &App::OnMenuExit);
mMenu.AddItem("Exit", cmd2);
MenuCallBack settingscmd(this, &App::OnMenuSettings);
mSettingId = mMenu.CreateMenuItem("Settings...", settingscmd);
MenuCallBack reinitcmd(this, &App::OnMenuReInit);
mMenu.CreateMenuItem("Re-Init!", reinitcmd);
MenuCallBack gostopcmd(this, &App::OnMenuGoStop);
mGoStopId = mMenu.CreateMenuItem("Go!", gostopcmd);
PaintCallBack pcmd(this, &App::OnPaint);
mWin.AddOnPaintCallBack(pcmd);
GenericCallBack gcmd(this, &App::OnMyEvent);
mWin.AddGenericCallBack(MYEVENT, gcmd);
mCalcThread = new CalcThread(mWin, MYEVENT, grid);
mCalcThread->Freeze();
mCalcThread->Start();
mWin.SetSize((GridInfo::colwidth * GridInfo::numcols) + 250, (GridInfo::rowheight
* GridInfo::numrows) + 250);
mOstream << "about to show " << std::endl;
mRc = mWin.Show();
}
void App::ProcessCommandLine(int argc, char** argv)
{
try
{
for (int i = 1; i < argc; i++)
mArgs.ProcessArg(argv[i]);
}
catch (std::string& err)
{
mStopProcessing = true;
if (err == "help")
{
mRc = cRc_OK;
}
else
{
mOstream << err << std::endl;
mRc = cRc_BadArgument;
}
}
if (mStopProcessing || !mArgs.IsValid())
{
mHelp.printOn(mOstream);
mRc = cRc_BadArgument;
}
}
|
|
|
#pragma once
#include "jFrameWin.h"
#include "jDialog.h"
#include "Help.h"
#include "CLArguments.h"
#include "jGraphics.h"
#include "CalcThread.h"
#include <ostream>
class App
{
public:
explicit App(std::ostream& os);
~App(void);
void Run(int argc, char** argv);
int ReturnCode();
protected:
void ProcessCommandLine(int argc, char** argv);
//int OnMenuCompare(const std::string& name);
int OnMenuExit(const std::string& name);
//int OnMenuSave(const std::string& name);
//int OnMenuUp(const std::string& name);
//int OnMenuDown(const std::string& name);
int OnMenuSettings(const std::string& name);
int OnSettingsDone(const std::string& name);
int OnMenuReInit(const std::string& name);
int OnMenuGoStop(const std::string& name);
int OnMyEvent(unsigned int p1);
int OnPaint(jGraphics& g);
private:
friend class Test;
std::ostream& mOstream;
Help mHelp;
int mRc;
bool mStopProcessing;
CLArguments mArgs;
CalcThread* mCalcThread;
jFrameWin mWin;
jDialog mDlg;
jMenu::MenuItem* mGoStopId;
jMenu::MenuItem* mSettingId;
int mGeneration;
};
|
|
|
#include "CalcThread.h"
#include "jFrameWin.h"
#include "Grid.h"
#include <wtypes.h>
#include <time.h>
#include <iostream>
//--------------------
CalcThread::CalcThread(jFrameWin& w, unsigned short callbackid, Grid& g) :
mWin(w), mGrid(g), mCallBackId(callbackid), mDone(false), mFrozen(false)
{
}
//--------------------
long CalcThread::Run()
{
enum
{
MS_PER_FRAME = 10
}; //min 30
clock_t start = 0;
clock_t end = 0;
while (!mDone)
{
if (!mFrozen)
{
//calculate an updated grid
start = clock();
mGrid.Calculate();
end = clock();
//refresh the screen
mWin.PostEvent(mCallBackId, 0, 0);
}
//delay until end of the frame, so we get at most 1 frame per MS_PER_FRAME milliseconds
//1 tick = 1/CLOCKS_PER_SEC seconds
if (end <= start)
{
Sleep(MS_PER_FRAME);
}
else
{
clock_t elapsed = end - start;
clock_t towait = MS_PER_FRAME - elapsed;
if (towait > MS_PER_FRAME)
towait = MS_PER_FRAME;
if (towait == 0)
towait = MS_PER_FRAME;
//std::cout << "x=towait=" << towait << std::endl;
if (towait > 0)
Sleep(towait);
}
}
return 0;
}
//----
void CalcThread::End()
{
mDone = true;
}
//----
void CalcThread::Freeze()
{
mFrozen = true;
}
//----
void CalcThread::Unfreeze()
{
mFrozen = false;
}
|
|
|
#ifndef CALCTHREAD_H_
#define CALCTHREAD_H_
#include "jBaseThread.h"
class jFrameWin;
class Grid;
class CalcThread : public jBaseThread
{
public:
CalcThread(jFrameWin& w, unsigned short callbackid, Grid& g);
long Run();
void End();
void Freeze();
void Unfreeze();
private:
jFrameWin& mWin;
Grid& mGrid;
unsigned short mCallBackId;
bool mDone;
bool mFrozen;
};
#endif /*CALCTHREAD_H_*/
|
|
|
#include "Animal.h"
#include "EnvironmentInfo.h"
#include "GridInfo.h"
#include "Cell.h"
#include <stdlib.h>
#include <iostream>
static jColor WHITE(255, 255, 255);
static jColor SUNSHINE(255, 255, 0);
static jColor GREEN9(0, 180, 0);
static jColor GREEN8(0, 205, 0);
static jColor GREEN7(0, 238, 0);
static jColor GREEN6(35, 255, 0);
static jColor GREEN5(75, 255, 0);
static jColor GREEN4(100, 255, 0);
static jColor GREEN3(127, 255, 25);
static jColor GREEN2(150, 255, 47);
static jColor GREEN1(173, 255, 80);
static jColor GREEN0(202, 255, 112);
static jColor DIRT0(240, 230, 140);
//---------
Cell::Cell() :
color(WHITE), mHasSunshine(false), mPlantLife(0), mDirt(0)
{
}
void Cell::InitAnimal()
{
mAnimal.SetInitial(gMasterAnimal);
}
//--
void Cell::SetSunshine()
{
int sun = rand() % 100;
if (sun < gEnvironment.SunPercentage)
mHasSunshine = true;
else
mHasSunshine = false;
}
//--
void Cell::UpdateColors()
{
if (mAnimal.Exists())
color = mAnimal.GetColor();
else if (mPlantLife > 90)
color = GREEN9;
else if (mPlantLife > 80)
color = GREEN8;
else if (mPlantLife > 70)
color = GREEN7;
else if (mPlantLife > 60)
color = GREEN6;
else if (mPlantLife > 50)
color = GREEN5;
else if (mPlantLife > 40)
color = GREEN4;
else if (mPlantLife > 30)
color = GREEN3;
else if (mPlantLife > 20)
color = GREEN2;
else if (mPlantLife > 10)
color = GREEN1;
else if (mPlantLife > 0)
color = GREEN0;
else if (mDirt > 0)
color = DIRT0;
else if (mHasSunshine)
color = SUNSHINE;
else
color = WHITE;
}
void Cell::UpdatePlantLife()
{
if (mHasSunshine)
{
//if there's dirt, plants grow faster
if (mDirt > 0)
{
mPlantLife += gEnvironment.PlantLifeIncWithDirt;
mDirt--; //use up the dirt
}
else
{
mPlantLife += gEnvironment.PlantLifeIncWithoutDirt;
}
}
else if (mPlantLife >= gEnvironment.PlantLifeDecWithoutSunshine) //no sunshine, high plantlife
{
mPlantLife -= gEnvironment.PlantLifeDecWithoutSunshine;
}
else //no sunshine, plantlife is dead
{
//there was some plants, convert it to dirt
if (mPlantLife > 0)
mDirt++;
mPlantLife = 0;
}
if (mPlantLife > 100)
mPlantLife = 100;
else if (mPlantLife < 0)
mPlantLife = 0;
}
void Cell::UpdateAnimal(int row, int col)
{
//if it's dead, check if a new animal should be created
if (!mAnimal.Exists())
{
CreateNewAnimal(row, col);
return;
}
//it's alive, so eat and make babies
mAnimal.Update(mPlantLife);
if (mAnimal.IsSociable())
{
MoveCloserToFriend(row, col);
}
else if (mAnimal.NotEnoughFood(mPlantLife))
{
//if current plantlife is low but animal has enough strength to move
//try to find more food...
MoveCloserToFood(row, col);
}
if (mAnimal.Exists())
{
//a live animal produces "dirt" every day
mDirt++;
}
else
{
//a dead animal produces a bit more "dirt"
mDirt += 2;
}
}
void Cell::MoveCloserToFood(int row, int col)
{
// move to a vacant neighboring square with the highest green
int bestrow = -1;
int bestcol = -1;
int bestgreen = -1;
int otherrow;
int othercol;
//row above
otherrow = row - 1;
othercol = col - 1;
if (IsBetterFood(otherrow, othercol, bestgreen))
{
bestrow = otherrow;
bestcol = othercol;
}
otherrow = row - 1;
othercol = col;
if (IsBetterFood(otherrow, othercol, bestgreen))
{
bestrow = otherrow;
bestcol = othercol;
}
otherrow = row - 1;
othercol = col + 1;
if (IsBetterFood(otherrow, othercol, bestgreen))
{
bestrow = otherrow;
bestcol = othercol;
}
//current row
otherrow = row;
othercol = col - 1;
if (IsBetterFood(otherrow, othercol, bestgreen))
{
bestrow = otherrow;
bestcol = othercol;
}
otherrow = row;
othercol = col + 1;
if (IsBetterFood(otherrow, othercol, bestgreen))
{
bestrow = otherrow;
bestcol = othercol;
}
//row below
otherrow = row + 1;
othercol = col - 1;
if (IsBetterFood(otherrow, othercol, bestgreen))
{
bestrow = otherrow;
bestcol = othercol;
}
otherrow = row + 1;
othercol = col;
if (IsBetterFood(otherrow, othercol, bestgreen))
{
bestrow = otherrow;
bestcol = othercol;
}
otherrow = row + 1;
othercol = col + 1;
if (IsBetterFood(otherrow, othercol, bestgreen))
{
bestrow = otherrow;
bestcol = othercol;
}
//found the best neighboring cell, so move...
if (bestrow != -1 && bestgreen > 0)
{
//move to the best neighboring cell, but it costs some energy to move...
Cells[bestrow][bestcol].mAnimal.Move(mAnimal);
}
}
// check if the grass is greener...
bool Cell::IsBetterFood(int r, int c, int& bestgreen)
{
if (r >= 0 && r < GridInfo::numrows && //is row in the grid bounds?
c >= 0 && c < GridInfo::numcols && // is col in the grid bounds?
!Cells[r][c].mAnimal.Exists()) // is the cell empty?
{
if (Cells[r][c].mPlantLife > bestgreen) // is the plantlife better than we've ever seen?
{
bestgreen = Cells[r][c].mPlantLife;
return true;
}
}
return false;
}
void Cell::MoveCloserToFriend(int row, int col)
{
int bestrow = -1;
int bestcol = -1;
int bestenergy = -1;
//initialize to the current cell's energy
//if it's the highest energy in the pack, it doesn't move
//all the other cells will move closer to it.
mAnimal.IsHigherThenSet(bestenergy);
int movetorow;
int movetocol;
//row above
movetorow = row - 1;
movetocol = col - 1;
if (movetorow >= 0 && movetorow < GridInfo::numrows && //is row in the grid bounds?
movetocol >= 0 && movetocol < GridInfo::numcols && // is col in the grid bounds?
!Cells[movetorow][movetocol].mAnimal.Exists() && // the space is empty
Cells[movetorow][movetocol].mPlantLife >= mPlantLife) //and the grass is ok
{
if (IsBetterFriend(row, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 1, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 2, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 2, col - 1, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 2, col, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
}
movetorow = row - 1;
movetocol = col;
if (movetorow >= 0 && movetorow < GridInfo::numrows && //is row in the grid bounds?
movetocol >= 0 && movetocol < GridInfo::numcols && // is col in the grid bounds?
!Cells[movetorow][movetocol].mAnimal.Exists() && // the space is empty
Cells[movetorow][movetocol].mPlantLife >= mPlantLife) //and the grass is ok
{
if (IsBetterFriend(row - 2, col - 1, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 2, col, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 2, col + 1, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
}
movetorow = row - 1;
movetocol = col + 1;
if (movetorow >= 0 && movetorow < GridInfo::numrows && //is row in the grid bounds?
movetocol >= 0 && movetocol < GridInfo::numcols && // is col in the grid bounds?
!Cells[movetorow][movetocol].mAnimal.Exists() && // the space is empty
Cells[movetorow][movetocol].mPlantLife >= mPlantLife) //and the grass is ok
{
if (IsBetterFriend(row - 2, col, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 2, col + 1, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 2, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 1, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
}
movetorow = row;
movetocol = col + 1;
if (movetorow >= 0 && movetorow < GridInfo::numrows && //is row in the grid bounds?
movetocol >= 0 && movetocol < GridInfo::numcols && // is col in the grid bounds?
!Cells[movetorow][movetocol].mAnimal.Exists() && // the space is empty
Cells[movetorow][movetocol].mPlantLife >= mPlantLife) //and the grass is ok
{
if (IsBetterFriend(row - 1, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 1, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
}
movetorow = row + 1;
movetocol = col + 1;
if (movetorow >= 0 && movetorow < GridInfo::numrows && //is row in the grid bounds?
movetocol >= 0 && movetocol < GridInfo::numcols && // is col in the grid bounds?
!Cells[movetorow][movetocol].mAnimal.Exists() && // the space is empty
Cells[movetorow][movetocol].mPlantLife >= mPlantLife) //and the grass is ok
{
if (IsBetterFriend(row, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 1, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 2, col + 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 2, col + 1, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 2, col, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
}
movetorow = row + 1;
movetocol = col;
if (movetorow >= 0 && movetorow < GridInfo::numrows && //is row in the grid bounds?
movetocol >= 0 && movetocol < GridInfo::numcols && // is col in the grid bounds?
!Cells[movetorow][movetocol].mAnimal.Exists() && // the space is empty
Cells[movetorow][movetocol].mPlantLife >= mPlantLife) //and the grass is ok
{
if (IsBetterFriend(row + 2, col + 1, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 2, col, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 2, col - 1, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
}
movetorow = row + 1;
movetocol = col - 1;
if (movetorow >= 0 && movetorow < GridInfo::numrows && //is row in the grid bounds?
movetocol >= 0 && movetocol < GridInfo::numcols && // is col in the grid bounds?
!Cells[movetorow][movetocol].mAnimal.Exists() && // the space is empty
Cells[movetorow][movetocol].mPlantLife >= mPlantLife) //and the grass is ok
{
if (IsBetterFriend(row + 2, col, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 2, col - 1, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 2, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row + 1, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
}
movetorow = row;
movetocol = col - 1;
if (movetorow >= 0 && movetorow < GridInfo::numrows && //is row in the grid bounds?
movetocol >= 0 && movetocol < GridInfo::numcols && // is col in the grid bounds?
!Cells[movetorow][movetocol].mAnimal.Exists() && // the space is empty
Cells[movetorow][movetocol].mPlantLife >= mPlantLife) //and the grass is ok
{
if (IsBetterFriend(row + 1, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
if (IsBetterFriend(row - 1, col - 2, bestenergy))
{
bestrow = movetorow;
bestcol = movetocol;
}
}
//found the best neighboring cell, so move...
if (bestrow != -1 && bestenergy > 0)
{
//std::cout << "move " << row << "," << col << " to " << bestrow << "," << bestcol << std::endl;
//move closer to the friend cell, but it costs some energy to move...
Cells[bestrow][bestcol].mAnimal.Move(mAnimal);
}
}
bool Cell::IsBetterFriend(int friendr, int friendc, int& bestenergy)
{
return friendr >= 0 && friendr < GridInfo::numrows && //is row in the grid bounds?
friendc >= 0 && friendc < GridInfo::numcols && // is col in the grid bounds?
Cells[friendr][friendc].mAnimal.Exists() && //friend exists
Cells[friendr][friendc].mAnimal.IsHigherThenSet(bestenergy);
}
void Cell::CreateNewAnimal(int row, int col)
{
//create a new animal if there are:
// - two occupied bordering cells
// - both with energy above a threshold
// - choose parents with the highest energy
// - the child's energy is a minimum value + a random extra value dependant on parent's energy
// - the child's energy will be subtracted from the parents
// find two parents in occupied neighboring squares
int parent1row = -1;
int parent1col = -1;
int parent1energy = -1;
int parent2row = -1;
int parent2col = -1;
int parent2energy = -1;
int otherrow;
int othercol;
// >be1 && >be2 choose be1
// >be1 && <=be2 choose be1
// <=be1 && >be2 choose be2
// <=be1 && <=be2 skip
//row above
otherrow = row - 1;
othercol = col - 1;
if (IsBetterParent(otherrow, othercol, parent1energy))
{
parent1row = otherrow;
parent1col = othercol;
}
else if (IsBetterParent(otherrow, othercol, parent2energy))
{
parent2row = otherrow;
parent2col = othercol;
}
otherrow = row - 1;
othercol = col;
if (IsBetterParent(otherrow, othercol, parent1energy))
{
parent1row = otherrow;
parent1col = othercol;
}
else if (IsBetterParent(otherrow, othercol, parent2energy))
{
parent2row = otherrow;
parent2col = othercol;
}
otherrow = row - 1;
othercol = col + 1;
if (IsBetterParent(otherrow, othercol, parent1energy))
{
parent1row = otherrow;
parent1col = othercol;
}
else if (IsBetterParent(otherrow, othercol, parent2energy))
{
parent2row = otherrow;
parent2col = othercol;
}
//current row
otherrow = row;
othercol = col - 1;
if (IsBetterParent(otherrow, othercol, parent1energy))
{
parent1row = otherrow;
parent1col = othercol;
}
else if (IsBetterParent(otherrow, othercol, parent2energy))
{
parent2row = otherrow;
parent2col = othercol;
}
otherrow = row;
othercol = col + 1;
if (IsBetterParent(otherrow, othercol, parent1energy))
{
parent1row = otherrow;
parent1col = othercol;
}
else if (IsBetterParent(otherrow, othercol, parent2energy))
{
parent2row = otherrow;
parent2col = othercol;
}
//row below
otherrow = row + 1;
othercol = col - 1;
if (IsBetterParent(otherrow, othercol, parent1energy))
{
parent1row = otherrow;
parent1col = othercol;
}
else if (IsBetterParent(otherrow, othercol, parent2energy))
{
parent2row = otherrow;
parent2col = othercol;
}
otherrow = row + 1;
othercol = col;
if (IsBetterParent(otherrow, othercol, parent1energy))
{
parent1row = otherrow;
parent1col = othercol;
}
else if (IsBetterParent(otherrow, othercol, parent2energy))
{
parent2row = otherrow;
parent2col = othercol;
}
otherrow = row + 1;
othercol = col + 1;
if (IsBetterParent(otherrow, othercol, parent1energy))
{
parent1row = otherrow;
parent1col = othercol;
}
else if (IsBetterParent(otherrow, othercol, parent2energy))
{
parent2row = otherrow;
parent2col = othercol;
}
//check if both parents were found...
// if they are above the threshold, then the cell is occupied
if (mAnimal.CanBeBorn(parent1energy, parent2energy))
{
mAnimal.BeBorn(Cells[parent1row][parent1col].mAnimal, Cells[parent2row][parent2col].mAnimal);
Cells[parent1row][parent1col].mAnimal.AdjustParentForBirthOf(mAnimal);
Cells[parent2row][parent2col].mAnimal.AdjustParentForBirthOf(mAnimal);
}
}
bool Cell::IsBetterParent(int r, int c, int& bestenergy)
{
return r >= 0 && r < GridInfo::numrows && //is row in the grid bounds?
c >= 0 && c < GridInfo::numcols && // is col in the grid bounds?
Cells[r][c].mAnimal.Exists() && Cells[r][c].mAnimal.IsHigherThenSet(bestenergy);
}
|
|
|
#ifndef CELL_H_
#define CELL_H_
#include "jColor.h"
#include "jRect.h"
#include "Animal.h"
class Cell
{
public:
Cell();
void UpdateColors();
void InitAnimal();
void UpdateAnimal(int row, int col);
void UpdatePlantLife();
void SetSunshine();
int GetType()
{
return mAnimal.GetType();
}
jColor color;
jRect rect;
private:
void MoveCloserToFood(int row, int col);
bool IsBetterFood(int r, int c, int& bestgreen);
void CreateNewAnimal(int row, int col);
bool IsBetterParent(int r, int c, int& bestenergy);
void MoveCloserToFriend(int row, int col);
bool IsBetterFriend(int friendr, int friendc, int& bestenergy);
//a cell can contain sunshine, plantlife, dirt and an animal (all optional)
Animal mAnimal;
bool mHasSunshine;
int mPlantLife;
int mDirt;
};
#endif /*CELL_H_*/
|
|
|
#include "CLArguments.h"
CLArguments::CLArguments(void)
{
mError = false;
}
CLArguments::~CLArguments(void)
{
}
void CLArguments::ProcessArg(char* arg)
{
if (IsSwitch(arg))
ProcessSwitch(arg);
else
SetPositionalArg(arg);
}
void CLArguments::SetPositionalArg(char* arg)
{
if (mSourceName.empty())
mSourceName = arg;
else if (mTargetName.empty())
mTargetName = arg;
else
{
mError = true;
throw std::string("unknown parameter");
}
}
bool CLArguments::IsGui()
{
return true;
}
bool CLArguments::IsConsole()
{
return !mSourceName.empty() && !mTargetName.empty();
}
bool CLArguments::IsValid()
{
return !mError && (IsConsole() || IsGui());
}
bool CLArguments::IsSwitch(char* arg)
{
return *arg == '-' || *arg == '/';
}
void CLArguments::ProcessSwitch(char* arg)
{
switch (toupper(arg[1]))
{
// case 'M': lpszMergedOutput = arg+2; break;
case '?':
throw std::string("help");
default:
throw std::string("unknown switch: '") + std::string(arg) + std::string("'");
}
}
|
|
|
#pragma once
#include <string>
#include <ostream>
class CLArguments
{
public:
CLArguments(void);
~CLArguments(void);
void ProcessArg(char* arg);
bool IsValid();
bool IsGui();
bool IsConsole();
private:
void SetPositionalArg(char* arg);
bool IsSwitch(char* arg);
void ProcessSwitch(char* arg);
bool mError;
std::string mSourceName;
std::string mTargetName;
};
|
|
|
#ifndef ENVIRONMENTINFO_H_
#define ENVIRONMENTINFO_H_
class EnvironmentInfo
{
public:
int SunPercentage;
int PlantLifeIncWithDirt;
int PlantLifeIncWithoutDirt;
int PlantLifeDecWithoutSunshine;
bool UseGenetics;
};
extern EnvironmentInfo gEnvironment;
#endif /*ENVIRONMENTINFO_H_*/
|
|
|
#include "GridInfo.h"
#include "Grid.h"
#include "jGraphics.h"
#include "EnvironmentInfo.h"
#include "Animal.h"
//#include "jGDIResourceLeak.h"
#include <iostream>
#include <stdlib.h>
#include <sstream>
//The grid
Cell Cells[GridInfo::numrows][GridInfo::numcols];
EnvironmentInfo gEnvironment;
static jColor WHITE(255, 255, 255);
//---------
void Grid::Init()
{
std::cout << "Grid::init " << std::endl;
InitEnvironment();
ReInit();
}
//---------
void Grid::ReInit()
{
std::cout << "Grid::reinit " << std::endl;
InitGrid();
InitAnimal();
Calculate();
}
void Grid::InitEnvironment()
{
//init the environment
gEnvironment.SunPercentage = 32; //the percentage of time the sun is shining in a cell
gEnvironment.PlantLifeIncWithDirt = 6; //the plant life increment with sun & dirt
gEnvironment.PlantLifeIncWithoutDirt = 3; //the plant life increment with sun & no dirt
gEnvironment.PlantLifeDecWithoutSunshine = 1; //the plant life decrement with no sun & no dirt
gEnvironment.UseGenetics = false; //do not use genetics for birthing babies
gMasterAnimal.Init();
}
//---------
void Grid::Calculate()
{
//std::cout << "x=Grid::Calculate " << std::endl;
UpdateSunshine();
UpdatePlantLife();
UpdateAnimal();
UpdateColors();
}
//---------
//-- update colors
void Grid::UpdateColors()
{
for (int col = 0; col < GridInfo::numcols; ++col)
{
for (int row = 0; row < GridInfo::numrows; ++row)
{
Cells[row][col].UpdateColors();
}
}
}
//---------
//-- update colors
void Grid::InitAnimal()
{
for (int col = 0; col < GridInfo::numcols; ++col)
{
for (int row = 0; row < GridInfo::numrows; ++row)
{
Cells[row][col].InitAnimal();
}
}
}
//---------
//-- update colors
void Grid::UpdateAnimal()
{
for (int col = 0; col < GridInfo::numcols; ++col)
{
for (int row = 0; row < GridInfo::numrows; ++row)
{
Cells[row][col].UpdateAnimal(row, col);
}
}
}
//---------
//-- update colors
void Grid::UpdatePlantLife()
{
for (int col = 0; col < GridInfo::numcols; ++col)
{
for (int row = 0; row < GridInfo::numrows; ++row)
{
Cells[row][col].UpdatePlantLife();
}
}
}
//---------
//-- update sunshine
void Grid::UpdateSunshine()
{
for (int col = 0; col < GridInfo::numcols; ++col)
{
for (int row = 0; row < GridInfo::numrows; ++row)
{
Cells[row][col].SetSunshine();
}
}
}
//---------
void Grid::InitGrid()
{
jRect rct;
rct.x = 1;
rct.y = 1;
rct.width = GridInfo::colwidth - 1;
rct.height = GridInfo::rowheight - 1;
//set up the grid
for (int col = 0; col < GridInfo::numcols; ++col)
{
for (int row = 0; row < GridInfo::numrows; ++row)
{
//calculate cell size
rct.x = (col * GridInfo::colwidth) + 1;
rct.y = (row * GridInfo::rowheight) + 1;
Cells[row][col].rect = rct;
}
}
}
//---------
void Grid::Update(int inc)
{
std::cout << "Grid::update " << std::endl;
jColor color;
for (int col = 0; col < GridInfo::numcols; ++col)
{
for (int row = 0; row < GridInfo::numrows; ++row)
{
color = Cells[row][col].color;
color.red += inc;
color.green += inc;
color.blue += inc;
Cells[row][col].color = color;
// std::cout << "update inc=" << inc << " r=" << (int) Cells[row][col].color.red << " g="
// << (int) Cells[row][col].color.green << " b=" << (int) Cells[row][col].color.blue
// << std::endl;
}
}
}
template <typename T>
void DrawLabelAndValue(jGraphics& g, const jRect& rct, const std::string& label, T value)
{
std::stringstream s;
s << label << value << std::endl;
g.FillRect(WHITE, rct);
g.Text(s.str(), rct);
}
void DrawLabel(jGraphics& g, const jRect& rct, const std::string& label)
{
std::stringstream s;
s << label << std::endl;
g.FillRect(WHITE, rct);
g.Text(s.str(), rct);
}
//---------
//-- paint the current grid
void Grid::Paint(jGraphics& g, int gen)
{
//std::cout << "Grid::paint " << std::endl;
int count[512];
memset(&count, 0x00, sizeof(count));
for (int col = 0; col < GridInfo::numcols; ++col)
{
for (int row = 0; row < GridInfo::numrows; ++row)
{
g.FillRect(Cells[row][col].color, Cells[row][col].rect);
int type = Cells[row][col].GetType();
if (type > 0 && type < 512)
{
count[type]++;
}
else
{
count[0]++;
}
}
}
if (count[1] == 0)
{
count[1] = 0;
}
for (int col = 0; col <= GridInfo::numcols; ++col)
{
g.Line(col * GridInfo::colwidth, 0, col * GridInfo::colwidth, GridInfo::numrows
* GridInfo::rowheight);
}
for (int row = 0; row <= GridInfo::numrows; ++row)
{
g.Line(0, row * GridInfo::rowheight, GridInfo::numcols * GridInfo::colwidth, row
* GridInfo::rowheight);
}
jRect rct;
rct.x = (GridInfo::numcols * GridInfo::colwidth) + 50;
rct.y = 0;
rct.height = 20;
rct.width = 300;
DrawLabelAndValue(g, rct, "Generation: ", gen);
rct.y += 20; //next line
DrawLabelAndValue(g, rct, "Non-animals : ", count[0]);
rct.y += 20; //next line
for (int i = 1; i < 20; i++)
{
std::stringstream s;
s << "Animal" << i << " Pop.: ";
DrawLabelAndValue(g, rct, s.str(), count[i]);
rct.y += 20; //next line
}
rct.y += 20; //next line
DrawLabel(g, rct, "Environment:");
rct.x += 10; //indent a little
rct.y += 20; //next line
DrawLabelAndValue(g, rct, "Sun: ", gEnvironment.SunPercentage);
rct.y += 20; //next line
DrawLabel(g, rct, "Plant Life: ");
rct.y += 20; //next line
rct.x += 10; //indent a little
DrawLabelAndValue(g, rct, "With sun + dirt : ", gEnvironment.PlantLifeIncWithDirt);
rct.y += 20; //next line
DrawLabelAndValue(g, rct, "With sun, no dirt: ", gEnvironment.PlantLifeIncWithoutDirt);
rct.y += 20; //next line
DrawLabelAndValue(g, rct, "No sun, no dirt : ", gEnvironment.PlantLifeDecWithoutSunshine);
rct.y += 20; //next line
DrawLabelAndValue(g, rct, "Use Genetics : ", gEnvironment.UseGenetics);
rct.y += 20; //next line
rct.x -= 10; //undent a little
rct.x -= 10; //undent a little
DrawLabel(g, rct, "Animal:");
rct.x += 10; //indent a little
rct.y += 20; //next line
DrawLabelAndValue(g, rct, "Sociability: ", gMasterAnimal.Sociability);
// rct.y += 20; //next line
// rct.y += 20; //next line
// rct.x = (GridInfo::numcols * GridInfo::colwidth) + 50;
// DrawLabel(g, rct, "Animal1:");
// rct.y += 20; //next line
// rct.x += 10; //indent a little
// //int ExistsPercentage;
// DrawLabelAndValue(g, rct, "Energy to move : ", mAnimal1.EnergyToMove);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Plants eaten/day : ", mAnimal1.PlantsEatenPerDay);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Energy from Plants/day : ", mAnimal1.EnergyGainedByEatingPlants);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Energy lost/day : ", mAnimal1.EnergyLossPerDay);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Youth threshold: ", mAnimal1.YoungThreshold);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Youth Energy Loss (%): ", mAnimal1.PercentageEnergyLossYoung);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Old Age threshold: ", mAnimal1.OldThreshold);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Old Age Energy Loss (%): ", mAnimal1.PercentageEnergyLossOld);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Energy to be a parent: ", mAnimal1.ParentEnergyThreshold);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Child's minimum energy: ", mAnimal1.ChildMinimumEnergy);
// rct.y += 20; //next line
// DrawLabelAndValue(g, rct, "Child's additional energy(%): ", mAnimal1.ChildPercentageAdditionalEnergy);
}
|
|
|
#ifndef GRID_H_
#define GRID_H_
#include "jColor.h"
#include "jRect.h"
#include "Animal.h"
class jGraphics;
class Grid
{
public:
void Init();
void ReInit();
void Update(int inc);
void Calculate();
void Paint(jGraphics& g, int gen);
private:
void InitEnvironment();
void InitGrid();
void InitAnimal();
void UpdateColors();
void UpdateSunshine();
void UpdatePlantLife();
void UpdateAnimal();
//EnvironmentInfo mEnv;
//Animal mAnimal1;
};
#endif /*GRID_H_*/
|
|
|
#ifndef GRIDINFO_H_
#define GRIDINFO_H_
#include "Cell.h"
namespace GridInfo
{
enum
{
numrows = 150, numcols = 150, colwidth = 3, rowheight = 3,
};
}
extern Cell Cells[GridInfo::numrows][GridInfo::numcols];
#endif /*GRIDINFO_H_*/
|
|
|
#include "Help.h"
#include <iostream>
Help::Help(void)
{
mHelpPrinted = false;
}
Help::~Help(void)
{
}
bool Help::isPrinted()
{
return mHelpPrinted;
}
void Help::printOn(std::ostream& os)
{
if (mHelpPrinted)
return;
os << "\nUsage: jLife \n"
"Optional switches (use either - or /):\n"
"/? This help\n" << std::endl;
mHelpPrinted = true;
}
|
|
|
#pragma once
#include <ostream>
class Help
{
public:
Help(void);
~Help(void);
void printOn(std::ostream& os);
bool isPrinted();
private:
bool mHelpPrinted;
};
|
|
|
#include "jBaseThread.h"
#include <wtypes.h>
//todo: clean up thread! resource leak.
//----
static DWORD WINAPI theThread(LPVOID parm)
{
return ((jBaseThread*) parm)->Run();
}
class jBaseThread::Private
{
public:
DWORD Tid;
};
//----
jBaseThread::jBaseThread() :
mPrivate(*new jBaseThread::Private())
{
}
//----
void jBaseThread::Start()
{
::CreateThread(0, 0, theThread, (LPVOID) this, 0, &mPrivate.Tid);
}
|
|
|
#pragma once
//-------------------------
class jBaseThread
{
public:
jBaseThread();
void Start();
virtual long Run() = 0;
private:
class Private;
Private& mPrivate;
};
|
|
|
#pragma once
class jCanvas
{
public:
jCanvas()
{
}
~jCanvas()
{
}
private:
//class Private;
//Private& mPrivate;
};
|
|
|
#ifndef JCOLOR_H_
#define JCOLOR_H_
struct jColor
{
unsigned char red;
unsigned char green;
unsigned char blue;
jColor() :
red(0), green(0), blue(0) //default to black
{
}
jColor(unsigned char r, unsigned char g, unsigned char b) :
red(r), green(g), blue(b)
{
}
jColor& operator =(const jColor& other)
{
red = other.red;
green = other.green;
blue = other.blue;
return *this;
}
};
#endif /*JCOLOR_H_*/
|
|
|
#pragma once
#include <list>
class jWinComponent;
typedef std::list<jWinComponent*> jComponentList;
|
|
|
#include "jDialog.h"
#include "jNativeWin.h"
class jDialog::Private
{
public:
jNativeDialog mWin;
};
jDialog::jDialog(void) :
mPrivate(*new jDialog::Private())
{
}
jDialog::~jDialog(void)
{
delete &mPrivate;
}
void jDialog::Create(const jWin& parent, const std::string& title, const jRect& rct)
{
mPrivate.mWin.Create(parent, title, rct);
}
void jDialog::Create(const jWin& parent, const std::string& title, int x, int y, int width,
int height)
{
jRect rct;
rct.x = x;
rct.y = y;
rct.width = width;
rct.height = height;
Create(parent, title, rct);
}
//void jDialog::Text(const std::string& s)
// {
// mPrivate.mWin.Text(s);
// }
unsigned long jDialog::Show()
{
return mPrivate.mWin.Show();
}
void jDialog::AddEdit(int defaultvalue, int& variable, int x, int y, int width, int height)
{
jRect rct;
rct.x = x;
rct.y = y;
rct.width = width;
rct.height = height;
AddEdit(defaultvalue, variable, rct);
}
void jDialog::AddEdit(int defaultvalue, int& variable, const jRect& rct)
{
mPrivate.mWin.AddEdit(defaultvalue, variable, rct);
}
void jDialog::AddEdit(double defaultvalue, double& variable, int x, int y, int width, int height)
{
jRect rct;
rct.x = x;
rct.y = y;
rct.width = width;
rct.height = height;
AddEdit(defaultvalue, variable, rct);
}
void jDialog::AddEdit(double defaultvalue, double& variable, const jRect& rct)
{
mPrivate.mWin.AddEdit(defaultvalue, variable, rct);
}
//void jDialog::AddEntry(const std::string& label, int& variable, int x, int y, int labelwidth,
// int entrywidth, int height)
// {
// mPrivate.mWin.AddEntry(label, variable, x, y, labelwidth, entrywidth, height);
// }
void jDialog::AddButton(const std::string& label, DialogCallBack& cmd, int x, int y, int width,
int height)
{
jRect rct;
rct.x = x;
rct.y = y;
rct.width = width;
rct.height = height;
AddButton(label, cmd, rct);
}
void jDialog::AddButton(const std::string& label, DialogCallBack& cmd, const jRect& rct)
{
mPrivate.mWin.AddButton(label, cmd, rct);
}
void jDialog::AddLabel(const std::string& label, int x, int y, int width, int height)
{
jRect rct;
rct.x = x;
rct.y = y;
rct.width = width;
rct.height = height;
AddLabel(label, rct);
}
void jDialog::AddLabel(const std::string& label, const jRect& rct)
{
mPrivate.mWin.AddLabel(label, rct);
}
void jDialog::Close(unsigned long returncode)
{
mPrivate.mWin.Close(returncode);
}
//void jDialog::AddEntry(const std::string& label, double& variable, int x, int y, int labelwidth, int entrywidth, int height);
//void jDialog::AddEntry(const std::string& label, std::string& variable, int x, int y, int labelwidth, int entrywidth, int height);
//void jDialog::SetSize(int width, int height);
|
|
|
#pragma once
#include "jICallBack.h"
#include <string>
class jWin;
class jRect;
class jDialog
{
public:
jDialog(void);
~jDialog(void);
void Create(const jWin& parent, const std::string& title, const jRect& rct);
void Create(const jWin& parent, const std::string& title, int x, int y, int width, int height);
//void Text(const std::string& s);
void AddEdit(int defaultvalue, int& variable, int x, int y, int width, int height);
void AddEdit(int defaultvalue, int& variable, const jRect& rct);
void AddEdit(double defaultvalue, double& variable, int x, int y, int width, int height);
void AddEdit(double defaultvalue, double& variable, const jRect& rct);
// void AddEntry(const std::string& label, int& variable, int x, int y, int labelwidth,
// int entrywidth, int height);
void AddButton(const std::string& label, DialogCallBack& cmd, int x, int y, int width,
int height);
void AddButton(const std::string& label, DialogCallBack& cmd, const jRect& rct);
void AddLabel(const std::string& label, int x, int y, int width, int height);
void AddLabel(const std::string& label, const jRect& rct);
unsigned long Show();
void Close(unsigned long returncode);
//void AddEntry(const std::string& label, double& variable, int x, int y, int labelwidth, int entrywidth, int height);
//void AddEntry(const std::string& label, std::string& variable, int x, int y, int labelwidth, int entrywidth, int height);
//void SetSize(int width, int height);
private:
class Private;
Private& mPrivate;
};
|
|
|
#include "jframewin.h"
#include "jNativeWin.h"
#include "jLayoutMgrEvenColumns.h"
#include "jMenu.h"
#include "jWinComponent.h"
//------------------------------------------------
class jFrameWin::Private
{
public:
jNativeFrameWin mWin;
jComponentList mComponents;
};
jWin jFrameWin::getWin()
{
return mPrivate.mWin.GetWin();
}
//------------------------------------------------
jFrameWin::jFrameWin(void) :
mPrivate(*new jFrameWin::Private())
{
}
//------------------------------------------------
jFrameWin::~jFrameWin(void)
{
delete &mPrivate;
}
//------------------------------------------------
void jFrameWin::Add(jWinComponent& win)
{
win.SetOwnerTo(mPrivate.mWin.GetWin());
mPrivate.mComponents.push_back(&win);
}
//------------------------------------------------
void jFrameWin::Text(const std::string& s)
{
mPrivate.mWin.Text(s.c_str());
}
//------------------------------------------------
void jFrameWin::Create(void)
{
mPrivate.mWin.CreateSkeletonWindow("jFrameWinClass");
}
//------------------------------------------------
void jFrameWin::Close()
{
mPrivate.mWin.Close();
}
//------------------------------------------------
long jFrameWin::Show(void)
{
//Layout(); todo: this code blows up if mPrivate.mComponents is empty
mPrivate.mWin.Show();
return mPrivate.mWin.StartMessageLoop();
}
//------------------------------------------------
void jFrameWin::SetActive(void)
{
mPrivate.mWin.SetActive();
}
//------------------------------------------------
void jFrameWin::SetSize(int width, int height)
{
mPrivate.mWin.SetSize(width, height);
}
//------------------------------------------------
void jFrameWin::Redraw(void)
{
mPrivate.mWin.Redraw();
}
//------------------------------------------------
void jFrameWin::Layout()
{
jLayoutMgrEvenColumns lm(2, 2);
lm.onLayout(mPrivate.mWin.GetSize(), mPrivate.mComponents);
}
//------------------------------------------------
jMenu jFrameWin::AddMenu() const
{
return jMenu::Create(mPrivate.mWin);
}
void jFrameWin::AddOnPaintCallBack(PaintCallBack& cmd) const
{
mPrivate.mWin.AddOnPaintCallBack(cmd);
}
void jFrameWin::PostEvent(unsigned short id, unsigned int parm1, unsigned int parm2)
{
mPrivate.mWin.PostEvent(id, parm1, parm2);
}
void jFrameWin::AddGenericCallBack(unsigned short id, GenericCallBack& cmd) const
{
mPrivate.mWin.AddGenericCallBack(id, cmd);
}
|
|
|
#pragma once
#include "jMenu.h"
#include "jICallBack.h"
#include <string>
//todo: ugh
#include "jWin.h"
class jWinComponent;
class jFrameWin
{
public:
jFrameWin(void);
~jFrameWin(void);
jWin getWin();
void Create();
void Close();
long Show();
void SetActive();
void Redraw();
void Text(const std::string& s);
void Add(jWinComponent& wcomp);
void SetSize(int width, int height);
jMenu AddMenu() const;
void AddOnPaintCallBack(PaintCallBack& cmd) const;
void PostEvent(unsigned short id, unsigned int parm1, unsigned int parm2);
void AddGenericCallBack(unsigned short id, GenericCallBack& cmd) const;
private:
void Layout();
class Private;
Private& mPrivate;
};
|
|
|
#pragma once
#include "jTypeList.h"
namespace jFunctor
{
template <typename T, class TList> class FnImpl;
//---
template <typename R> class FnImpl<R, TYPELIST0()>
{
public:
virtual ~FnImpl()
{
}
virtual R operator()() = 0;
};
//---
template <typename R, typename P1> class FnImpl<R, TYPELIST1(P1) >
{
public:
virtual ~FnImpl()
{
}
virtual R operator()(P1) = 0;
};
//---
template <typename R, typename P1, typename P2> class FnImpl<R, TYPELIST2(P1, P2) >
{
public:
virtual ~FnImpl()
{
}
virtual R operator()(P1, P2) = 0;
};
//---
template <class ParentFn, typename PointerToObj, typename PointerToMemFn> class MemFnHandler : public FnImpl<
typename ParentFn::ResultType, typename ParentFn::ParmList>
{
public:
typedef typename ParentFn::ResultType ResultType;
//--
MemFnHandler(const PointerToObj& pObj, PointerToMemFn pMemFn) :
mObj(pObj), mMemFn(pMemFn)
{
}
//--
ResultType operator()()
{
return ((*mObj).*mMemFn)();
}
//--
ResultType operator()(typename ParentFn::TParm1 p1)
{
return ((*mObj).*mMemFn)(p1);
}
//--
ResultType operator()(typename ParentFn::TParm1 p1, typename ParentFn::TParm2 p2)
{
return ((*mObj).*mMemFn)(p1, p2);
}
private:
PointerToObj mObj;
PointerToMemFn mMemFn;
};
//---
template <typename R, class TList> class Fnct
{
public:
typedef R ResultType;
typedef TList ParmList;
typedef typename TL::TypeAt<TList, 0, TL::NullType>::Type TParm1;
typedef typename TL::TypeAt<TList, 1, TL::NullType>::Type TParm2;
Fnct() :
spImpl_(0)
{
}
template <typename Obj, typename Fun> Fnct(const Obj& obj, const Fun& fun) :
spImpl_(new MemFnHandler<Fnct, Obj, Fun> (obj, fun))
{
}
Fnct(const Fnct& other)
{
spImpl_ = other.spImpl_;
}
Fnct& operator=(const Fnct& other)
{
spImpl_ = other.spImpl_;
return *this;
}
//todo: use auto-ptr explicit Functor(std::auto_ptr<Impl> spImpl);
R operator()()
{
return spImpl_->operator ()();
}
R operator()(TParm1 p1)
{
return spImpl_->operator ()(p1);
}
R operator()(TParm1 p1, TParm2 p2)
{
return spImpl_->operator ()(p1, p2);
}
private:
typedef FnImpl<R, TList> Impl;
Impl* spImpl_;
};
}
|
|
|
#include "jGDIResourceLeak.h"
#define _WIN32_WINNT 0x0600
#include <windows.h>
#include <iostream>
jGDIResourceLeak::jGDIResourceLeak()
{
_guiResCount = ::GetGuiResources(::GetCurrentProcess(), GR_GDIOBJECTS);
}
jGDIResourceLeak::~jGDIResourceLeak()
{
int leaks = ::GetGuiResources(::GetCurrentProcess(), GR_GDIOBJECTS) - _guiResCount;
if (leaks != 0)
{
std::cout << "GDI Resources: leaked: " << leaks << " rescount=" << _guiResCount << std::endl;
}
else
{
std::cout << "GDI Resources: no leaks: " << leaks << " rescount=" << _guiResCount << std::endl;
}
}
|
|
|
#ifndef jGDIRESOURCELEAK_H_
#define jGDIRESOURCELEAK_H_
class jGDIResourceLeak
{
public:
explicit jGDIResourceLeak();
~jGDIResourceLeak();
private:
unsigned _guiResCount;
};
#endif /*GDIRESOURCELEAK_H_*/
|
|
|
#include "jGraphics.h"
#include "jNativeWin.h"
#include "jRect.h"
#include <iostream>
jGraphics::jGraphics(jNativeGraphics& g) :
mGraphics(g)
{
}
jGraphics::~jGraphics()
{
; //nothing to do
}
void jGraphics::Line(int x1, int y1, int x2, int y2)
{
mGraphics.Line(x1, y1, x2, y2);
}
void jGraphics::FillRect(const jColor& color, int x1, int y1, int x2, int y2)
{
jRect rct;
rct.x = x1;
rct.y = y1;
rct.width = x2 - x1;
rct.height = y2 - y1;
FillRect(color, rct);
}
void jGraphics::FillRect(const jColor& color, const jRect& rct)
{
mGraphics.FillRect(color, rct);
}
void jGraphics::Text(const std::string& txt, const jRect& rct)
{
mGraphics.Text(txt, rct);
}
|
|
|
#pragma once
#include <string>
class jNativeGraphics;
class jRect;
class jColor;
class jGraphics
{
public:
jGraphics(jNativeGraphics& g);
~jGraphics();
void Line(int x1, int y1, int x2, int y2);
void FillRect(const jColor& color, int x1, int y1, int x2, int y2);
void FillRect(const jColor& color, const jRect& rct);
void Text(const std::string& txt, const jRect& rct);
private:
jNativeGraphics& mGraphics;
};
|
|
|
#pragma once
#include <string>
#include "jFunctor.h"
//used for callbacks when a menu item is clicked
// returns an int
// parm1: a string indicating the name of the menu item
typedef jFunctor::Fnct<int, TYPELIST1(const std::string&)> MenuCallBack;
//used for OnPaint callbacks
class jGraphics;
typedef jFunctor::Fnct<int, TYPELIST1(jGraphics&)> PaintCallBack;
//used for Generic callbacks
//typedef Functor::Fnct<int, TL::TypeList<unsigned int, unsigned int > > GenericCallBack;
typedef jFunctor::Fnct<int, TYPELIST1(unsigned int)> GenericCallBack;
//used for Dialog button callbacks
typedef jFunctor::Fnct<int, TYPELIST1(const std::string&)> DialogCallBack;
|
|
|
#include "jlistbox.h"
#include "jNativeWin.h"
//------------------------------------------------
class jListBox::Private
{
public:
jNativeListBox mWin;
};
//------------------------------------------------
jListBox::jListBox() :
mPrivate(*new jListBox::Private())
{
mPrivate.mWin.CreateSkeletonWindow();
}
//------------------------------------------------
jListBox::~jListBox(void)
{
delete &mPrivate;
}
//------------------------------------------------
void jListBox::SetOwnerTo(const jWin& owner)
{
mPrivate.mWin.ConvertToChildWindow();
mPrivate.mWin.SetParent(owner);
mPrivate.mWin.SetSize(0, 0, 100, 200);
mPrivate.mWin.Show();
}
//------------------------------------------------
void jListBox::SetSize(int x, int y, int width, int height)
{
mPrivate.mWin.SetSize(x, y, width, height);
}
//------------------------------------------------
void jListBox::AddString(const std::string& s)
{
mPrivate.mWin.AddString(s.c_str());
}
|
|
|
#pragma once
#include "jWinComponent.h"
#include <string>
class jListBox : public jWinComponent
{
public:
jListBox();
virtual ~jListBox(void);
void SetOwnerTo(const jWin& owner);
void SetSize(int x, int y, int width, int height);
void AddString(const std::string& s);
private:
class Private;
Private& mPrivate;
};
|
|
|
#include "jMenu.h"
#include "jNativeWin.h"
jMenu jMenu::Create(jNativeFrameWin& nfw)
{
return jMenu(nfw);
}
jMenu::jMenu(jNativeFrameWin& nfw) :
mMenu(*new jNativeMenu(nfw))
{
}
jMenu::~jMenu(void)
{
delete &mMenu;
}
void jMenu::CreateDropDown(const std::string& name)
{
mMenu.CreateDropDown(name);
}
jMenu::MenuItem* jMenu::CreateMenuItem(const std::string& name, MenuCallBack& fn)
{
return mMenu.CreateMenuItem(name, fn);
}
jMenu::MenuItem* jMenu::AddItem(const std::string& name, MenuCallBack& fn)
{
return mMenu.AddItem(name, fn);
}
|
|
|
#pragma once
#include "jICallBack.h"
#include <string>
class jNativeMenu;
class jNativeFrameWin;
class jMenu
{
public:
class MenuItem
{
public:
virtual void SetMenuItemText(const std::string& newname) = 0;
virtual void SetEnabled(bool enable) = 0;
};
static jMenu Create(jNativeFrameWin& nfw);
~jMenu(void);
void CreateDropDown(const std::string& name);
MenuItem* CreateMenuItem(const std::string& name, MenuCallBack& fn);
MenuItem* AddItem(const std::string& name, MenuCallBack& fn);
private:
explicit jMenu(jNativeFrameWin& nfw);
jNativeMenu& mMenu;
};
|
|
|
#include "jNativeWin.h"
#include "jGraphics.h"
#include "jICallBack.h"
#include "jFunctor.h"
#include "jWin.h"
#include "jColor.h"
#include "jRect.h"
//#include "jGDIResourceLeak.h"
#include <windows.h>
#include <windowsx.h>
#include <CommCtrl.h>
#include <map>
#include <iostream>
#include <sstream>
jNativeWin::jNativeWin(void)
{
}
jNativeWin::~jNativeWin(void)
{
}
jRect jNativeWin::GetSize()
{
RECT rct;
::GetClientRect((HWND) mWin.mHwnd, &rct);
jRect jr;
jr.x = rct.top;
jr.y = rct.left;
jr.width = rct.right - rct.left;
jr.height = rct.bottom - rct.top;
return jr;
}
void jNativeWin::CreateSkeletonWindow(const std::string& className)
{
mWin.mHwnd = ::CreateWindow(
className.c_str(), // name of window class
"", // title-bar string
WS_POPUP|WS_BORDER, // top-level window
0, // default horizontal position
0, // default vertical position
0, // default width
0, // default height
(HWND) 0, // no owner window
(HMENU) 0, // use class menu
GetModuleHandle(NULL), // handle to application instance
(LPVOID) 0); // no window-creation data
//DWORD gle = GetLastError();
::SetWindowLong((HWND) mWin.mHwnd, GWL_USERDATA, (LONG) this);
}
void jNativeWin::ConvertToChildWindow()
{
DWORD style = GetWindowStyle((HWND) mWin.mHwnd);
style |= WS_CHILD;
style ^= WS_POPUP;
::SetWindowLong((HWND) mWin.mHwnd, GWL_STYLE, style);
}
void jNativeWin::Text(const std::string& s)
{
::SetWindowText((HWND) mWin.mHwnd, s.c_str());
}
void jNativeWin::SetParent(const jWin& parent)
{
::SetParent((HWND) mWin.mHwnd, (HWND) parent.mHwnd);
}
void jNativeWin::SetSize(int x, int y, int width, int height)
{
::SetWindowPos((HWND) mWin.mHwnd, HWND_TOP, x, y, width, height, 0);
}
void jNativeWin::Show()
{
::ShowWindow((HWND) mWin.mHwnd, SW_SHOW);
::UpdateWindow((HWND) mWin.mHwnd);
}
void jNativeWin::SetActive()
{
//::SetActiveWindow((HWND) mWin.mHwnd);
//::SetForegroundWindow((HWND) mWin.mHwnd);
::SetFocus((HWND) mWin.mHwnd);
}
void jNativeWin::Close()
{
::PostQuitMessage(0);
}
void jNativeWin::Redraw()
{
//::InvalidateRect((HWND) mWin.mHwnd, 0, TRUE);
::InvalidateRect((HWND) mWin.mHwnd, 0, FALSE);
}
//------------------------------------------------
typedef std::pair<MenuCallBack, std::string> MenuCommandInfo;
typedef std::map<short, MenuCommandInfo> MenuCommandListenerList;
typedef std::map<short, GenericCallBack> GenericCommandListenerList;
class jNativeFrameWin::Private
{
public:
MenuCommandListenerList MenuCommandListeners;
GenericCommandListenerList GenericCommandListeners;
PaintCallBack PaintCmd;
};
jNativeFrameWin::jNativeFrameWin() :
mPrivate(*new jNativeFrameWin::Private)
{
}
void jNativeFrameWin::CreateSkeletonWindow(const std::string& className)
{
RegisterWinClass(className);
CreateFrameWin(className);
}
//----
class PaintDeviceContext
{
public:
PaintDeviceContext(HWND hwnd)
{
mHwnd = hwnd;
mHdc = ::BeginPaint(mHwnd, &mPaintStruct);
// std::cout << "x=: paint: "
// << mPaintStruct.rcPaint.left << " "
// << mPaintStruct.rcPaint.right << " "
// << mPaintStruct.rcPaint.top << " "
// << mPaintStruct.rcPaint.bottom << " "
// << std::endl;
}
~PaintDeviceContext()
{
::EndPaint(mHwnd, &mPaintStruct);
}
//protected:
HDC mHdc;
PAINTSTRUCT mPaintStruct;
HWND mHwnd;
};
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
jNativeFrameWin* This = (jNativeFrameWin*) ::GetWindowLong(hwnd, GWL_USERDATA);
if (This == 0)
return DefWindowProc(hwnd, uMsg, wParam, lParam);
//is this one of our own messages?
if (uMsg >= WM_APP && uMsg <= WM_APP + 0x3FFF)
{
This->HandleGenericEvent(uMsg - WM_APP, (unsigned int) wParam, (unsigned int) lParam);
return 0; //todo: use return code from HandleGenericEvent??
}
switch (uMsg)
{
//WM_CLOSE ; def handler sends a destroy
//WM_DESTROY; //about to end, cleanup.
case WM_DESTROY:
std::cout << "x=wm_destroy: " << std::endl;
::PostQuitMessage(0);
return 0;
//wParam lo 16 => WM_LBUTTONDOWN(x201), WM_RBUTTONDOWN(x204)
//wParam hi 16 => child id
//lParam => hwnd of child
case WM_PARENTNOTIFY:
uMsg = uMsg;
break;
//wparam lower 16 is the id of the menu item
case WM_COMMAND:
if (HIWORD(wParam) == 0)
{
This->HandleMenuCommand(LOWORD(wParam));
}
return 0;
//WM_PAINT; redraw the screen
case WM_PAINT:
{
PaintDeviceContext dc(hwnd);
jNativeGraphics ng((unsigned long) dc.mHdc);
jGraphics g(ng);
This->Paint(g);
}
return 0;
default:
; //uMsg=uMsg;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//--
void jNativeFrameWin::PostEvent(unsigned short id, unsigned int parm1, unsigned int parm2)
{
//todo: check if id is registered in GenericCommandListeners
PostMessage((HWND) mWin.mHwnd, WM_APP + id, parm1, parm2);
}
void jNativeFrameWin::AddGenericCallBack(unsigned short id, GenericCallBack& cmd) const
{
//todo: WM_APP = 0x8000 -> 0xBFFF inclusive, so check if id = 0 -> 16383 inclusive
mPrivate.GenericCommandListeners[id] = cmd;
}
void jNativeFrameWin::HandleGenericEvent(unsigned short id, unsigned int parm1, unsigned int parm2)
{
GenericCommandListenerList::iterator pos = mPrivate.GenericCommandListeners.find(id);
if (pos == mPrivate.GenericCommandListeners.end())
return;
GenericCallBack cb = pos->second;
cb(parm1);
}
//--
void jNativeFrameWin::SetMenuCommandCallBack(short itemid, const std::string& name,
MenuCallBack& fn)
{
mPrivate.MenuCommandListeners[itemid] = make_pair(fn, name);
}
void jNativeFrameWin::UpdateMenuCommandCallBack(short itemid, const std::string& newname)
{
MenuCommandListenerList::iterator pos = mPrivate.MenuCommandListeners.find(itemid);
if (pos == mPrivate.MenuCommandListeners.end())
return;
(pos->second).second = newname;
}
void jNativeFrameWin::HandleMenuCommand(short itemid)
{
MenuCommandListenerList::iterator pos = mPrivate.MenuCommandListeners.find(itemid);
if (pos == mPrivate.MenuCommandListeners.end())
return;
MenuCommandInfo info = pos->second;
(info.first)(info.second);
}
//--
void jNativeFrameWin::AddOnPaintCallBack(PaintCallBack& cmd) const
{
mPrivate.PaintCmd = cmd;
}
void jNativeFrameWin::Paint(jGraphics& g)
{
mPrivate.PaintCmd(g);
}
void jNativeFrameWin::RegisterWinClass(const std::string& className)
{
WNDCLASSEX wclass;
wclass.cbSize = sizeof(wclass);
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wclass.hIcon = LoadIcon(0, IDI_INFORMATION);
wclass.hInstance = GetModuleHandle(NULL);
wclass.lpfnWndProc = WindowProc;
wclass.lpszClassName = className.c_str();
wclass.lpszMenuName = 0;
wclass.style = CS_HREDRAW | CS_VREDRAW;
wclass.hIconSm = 0;
::RegisterClassEx(&wclass);
//DWORD gle = GetLastError();
}
void jNativeFrameWin::CreateFrameWin(const std::string& className)
{
mWin.mHwnd = ::CreateWindow(
className.c_str(), // name of window class
"", // title-bar string
WS_OVERLAPPEDWINDOW, // top-level window
CW_USEDEFAULT, // default horizontal position
CW_USEDEFAULT, // default vertical position
CW_USEDEFAULT, // default width
CW_USEDEFAULT, // default height
(HWND) 0, // no owner window
(HMENU) 0, // use class menu
GetModuleHandle(NULL), // handle to application instance
(LPVOID) 0); // no window-creation data
//DWORD gle = GetLastError();
::SetWindowLong((HWND) mWin.mHwnd, GWL_USERDATA, (LONG) this);
}
void jNativeFrameWin::SetSize(int width, int height)
{
::SetWindowPos((HWND) mWin.mHwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
}
long jNativeFrameWin::StartMessageLoop()
{
MSG msg;
for (;;)
{
BOOL rc = ::GetMessage(&msg, NULL, 0, 0);
if (rc == 0)
{
std::cout << "x=wm_quit: " << "\n";
break; //WM_QUIT
}
if (rc == -1)
{
std::cout << "x=error in msgloop: " << "\n";
break; //error.
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
return (long) msg.wParam;
}
//-------------------------------------------------------
void jNativeListBox::CreateSkeletonWindow()
{
jNativeWin::CreateSkeletonWindow(WC_LISTBOX);
}
//-------------------------------------------------------
void jNativeListBox::AddString(const std::string& s)
{
ListBox_AddString((HWND) mWin.mHwnd, s.c_str());
}
//-------------------------------------------------------
class jNativeMenuItem : public jMenu::MenuItem
{
public:
jNativeMenuItem(jNativeFrameWin& fw, HWND hwnd, HMENU mb, unsigned int id) :
framewin(fw), framehwnd(hwnd), menubar(mb), menuid(id)
{
}
void SetMenuItemText(const std::string& newname)
{
MENUITEMINFO mi;
memset(&mi, 0x00, sizeof(mi));
mi.cbSize = sizeof(mi);
mi.fMask = MIIM_TYPE;
mi.fType = MFT_STRING;
mi.dwTypeData = const_cast<char*> (newname.c_str());
mi.cch = newname.length();
BOOL rc = ::SetMenuItemInfo(menubar, //the menu
menuid, //the menu item id
FALSE, //it's an id
&mi);
rc = ::DrawMenuBar(framehwnd);
//DWORD gle = ::GetLastError();
framewin.UpdateMenuCommandCallBack(menuid, newname);
}
void SetEnabled(bool enable)
{
::EnableMenuItem(menubar, menuid, (enable ? MF_ENABLED : MF_GRAYED));
// DWORD gle = ::GetLastError();
// std::cout << "x=enable: rc=" << rc << " gle=" << gle << std::endl;
}
private:
jNativeFrameWin& framewin;
HWND framehwnd;
HMENU menubar;
unsigned int menuid;
};
typedef void (jNativeMenu::* AttachFnType)();
class jNativeMenu::Private
{
public:
Private(jNativeFrameWin& w, HWND hwnd) :
menubar(0), submenu(0), framewin(w), framehwnd(hwnd)
{
}
HMENU menubar;
HMENU submenu;
jNativeFrameWin& framewin;
HWND framehwnd;
AttachFnType attach;
static unsigned int menuid;
};
unsigned int jNativeMenu::Private::menuid = 9000;
jNativeMenu::jNativeMenu(jNativeFrameWin& w) :
mPrivate(*new jNativeMenu::Private(w, (HWND) w.GetWin().mHwnd))
{
mPrivate.menubar = ::CreateMenu();
mPrivate.attach = &jNativeMenu::AttachMenu;
}
jNativeMenu::~jNativeMenu()
{
delete &mPrivate;
}
void jNativeMenu::AttachMenu()
{
::SetMenu(mPrivate.framehwnd, mPrivate.menubar);
mPrivate.attach = &jNativeMenu::NullAttach;
}
void jNativeMenu::NullAttach()
{
//do nothing
}
void jNativeMenu::CreateDropDown(const std::string& name)
{
mPrivate.submenu = ::CreatePopupMenu();
::AppendMenu(mPrivate.menubar, MF_STRING | MF_POPUP, (UINT_PTR) mPrivate.submenu, name.c_str());
}
jMenu::MenuItem* jNativeMenu::AddItem(const std::string& name, MenuCallBack& fn)
{
mPrivate.framewin.SetMenuCommandCallBack(mPrivate.menuid, name, fn);
::AppendMenu(mPrivate.submenu, MF_STRING, mPrivate.menuid, name.c_str());
mPrivate.menuid++;
(this->*(mPrivate.attach))();
return new jNativeMenuItem(mPrivate.framewin, mPrivate.framehwnd, mPrivate.menubar,
mPrivate.menuid - 1);
}
jMenu::MenuItem* jNativeMenu::CreateMenuItem(const std::string& name, MenuCallBack& fn)
{
mPrivate.framewin.SetMenuCommandCallBack(mPrivate.menuid, name, fn);
::AppendMenu(mPrivate.menubar, MF_STRING, mPrivate.menuid, name.c_str());
mPrivate.menuid++;
return new jNativeMenuItem(mPrivate.framewin, mPrivate.framehwnd, mPrivate.menubar,
mPrivate.menuid - 1);
}
//-------------------------------------------------------
class jNativeGraphics::Private
{
public:
Private(unsigned long h) :
hdc((HDC) h)
{
}
HDC hdc;
};
jNativeGraphics::jNativeGraphics(unsigned long hdc) :
mPrivate(*new jNativeGraphics::Private(hdc))
{
}
jNativeGraphics::~jNativeGraphics()
{
delete &mPrivate;
}
void jNativeGraphics::Line(int x1, int y1, int x2, int y2)
{
::MoveToEx(mPrivate.hdc, x1, y1, 0);
::LineTo(mPrivate.hdc, x2, y2);
}
void jNativeGraphics::FillRect(const jColor& color, const jRect& jrct)
{
RECT rct;
rct.left = jrct.x;
rct.top = jrct.y;
rct.right = jrct.x + jrct.width;
rct.bottom = jrct.y + jrct.height;
COLORREF c = RGB(color.red, color.green, color.blue);
HBRUSH b = ::CreateSolidBrush(c);
::FillRect(mPrivate.hdc, &rct, b);
::DeleteObject(b);
}
void jNativeGraphics::Text(const std::string& txt, const jRect& jrct)
{
RECT rct;
rct.left = jrct.x;
rct.top = jrct.y;
rct.right = jrct.x + jrct.width;
rct.bottom = jrct.y + jrct.height;
::DrawText(mPrivate.hdc, txt.c_str(), txt.length(), &rct, DT_LEFT);
}
typedef std::pair<DialogCallBack, std::string> DialogCommandInfo;
typedef std::map<short, DialogCommandInfo> DialogCommandListenerList;
class EBVFunctor
{
public:
virtual void Save(char* buf) = 0;
};
typedef std::map<short, EBVFunctor*> EditBoxVariablesList;
class EBVFunctorInt : public EBVFunctor
{
public:
EBVFunctorInt(int& v) :
Variable(&v)
{
}
void Save(char* buf)
{
int x = atoi(buf);
*Variable = x;
}
int* Variable;
};
class EBVFunctorDouble : public EBVFunctor
{
public:
EBVFunctorDouble(double& v) :
Variable(&v)
{
}
void Save(char* buf)
{
double x = atof(buf);
*Variable = x;
}
double* Variable;
};
static BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
jNativeDialog* This = (jNativeDialog*) ::GetWindowLong(hwnd, GWL_USERDATA);
// if (uMsg != 32 && uMsg != 132)
// std::cout << "dlg: x=" << uMsg << std::endl;
switch (uMsg)
{
case WM_INITDIALOG:
{
jNativeDialog* This = (jNativeDialog*) lParam;
std::cout << "dlg: x=wm_initdialog: This=" << This << std::endl;
This->SetWindowHandle(hwnd);
::SetWindowLong(hwnd, GWL_USERDATA, (LONG) This);
return 0;
}
case WM_DESTROY:
std::cout << "dlg: x=wm_destroy: " << std::endl;
return 0;
//wparam lower 16 is the id of the command item
case WM_COMMAND:
{
if (HIWORD(wParam) == 0)
{
This->HandleDialogEvent(LOWORD(wParam), (unsigned int) wParam, (unsigned int) lParam);
}
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//----------------------------------------
class jNativeDialog::Private
{
public:
//---------
void init(HWND p)
{
//todo: check if additional structs go past buf size (see below)
lpdt = (LPDLGTEMPLATE) calloc(4096, 1);
lpw = (LPWORD) lpdt;
numcontrols = 0;
parent = p;
}
//from http://msdn.microsoft.com/en-us/library/ms644997%28VS.85%29.aspx
//Each DLGITEMTEMPLATE structure in the template must be aligned on a DWORD boundary.
///The class and title arrays must be aligned on WORD boundaries.
//The creation data array must be aligned on a WORD boundary.
//from http://msdn.microsoft.com/en-us/library/ms644997%28VS.85%29.aspx
// 0x0080 Button
// 0x0081 Edit
// 0x0082 Static
// 0x0083 List box
// 0x0084 Scroll bar
// 0x0085 Combo box
//---------
void DefEdit(const std::string& text, const jRect& position)
{
lpw = lpDwordAlign(lpw);
LPDLGITEMTEMPLATE lpdit = (LPDLGITEMTEMPLATE) lpw;
lpdit->x = position.x;
lpdit->y = position.y;
lpdit->cx = position.width;
lpdit->cy = position.height;
lpdit->id = numcontrols;
lpdit->style = WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_CENTER;
lpw = (LPWORD) (lpdit + 1); //bump lpw past DLGITEMTEMPLATE structure
lpw = lpWordAlign(lpw);
*lpw++ = 0xFFFF;
*lpw++ = 0x0081; // Edit class
lpw = lpWordAlign(lpw);
LPWSTR lpwsz = (LPWSTR) lpw;
//todo: the 50 is a max size of bytes for the text variable.
int nchar = MultiByteToWideChar(CP_ACP, 0, text.c_str(), -1, lpwsz, 50);
lpw += nchar;
lpw = lpWordAlign(lpw); // Align creation data on DWORD boundary
*lpw++ = 0; // No creation data
numcontrols++;
}
//---------
void DefButton(const std::string& text, const jRect& position)
{
lpw = lpDwordAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
LPDLGITEMTEMPLATE lpdit = (LPDLGITEMTEMPLATE) lpw;
lpdit->x = position.x;
lpdit->y = position.y;
lpdit->cx = position.width;
lpdit->cy = position.height;
lpdit->id = numcontrols;
lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
lpw = (LPWORD) (lpdit + 1);
lpw = lpWordAlign(lpw);
*lpw++ = 0xFFFF;
*lpw++ = 0x0080; // Button class
lpw = lpWordAlign(lpw);
LPWSTR lpwsz = (LPWSTR) lpw;
int nchar = MultiByteToWideChar(CP_ACP, 0, text.c_str(), -1, lpwsz, 50);
lpw += nchar;
lpw = lpWordAlign(lpw); // Align creation data on DWORD boundary
*lpw++ = 0; // No creation data
numcontrols++;
}
//---------
void DefLabel(const std::string& text, const jRect& position)
{
lpw = lpDwordAlign(lpw); // Align DLGITEMTEMPLATE on DWORD boundary
LPDLGITEMTEMPLATE lpdit = (LPDLGITEMTEMPLATE) lpw;
lpdit->x = position.x;
lpdit->y = position.y;
lpdit->cx = position.width;
lpdit->cy = position.height;
lpdit->id = numcontrols;
lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
lpw = (LPWORD) (lpdit + 1);
lpw = lpWordAlign(lpw);
*lpw++ = 0xFFFF;
*lpw++ = 0x0082; // Static class
lpw = lpWordAlign(lpw);
LPWSTR lpwsz = (LPWSTR) lpw;
int nchar = MultiByteToWideChar(CP_ACP, 0, text.c_str(), -1, lpwsz, 50);
lpw += nchar;
lpw = lpWordAlign(lpw);
*lpw++ = 0; // No creation data
numcontrols++;
}
//---------
void DefDialog(const std::string& text, const jRect& position)
{
LPDLGTEMPLATE lpdt = (LPDLGTEMPLATE) lpw;
lpdt->style = WS_POPUP | WS_BORDER | DS_MODALFRAME | WS_CAPTION;
lpdt->x = position.x;
lpdt->y = position.y;
lpdt->cx = position.width;
lpdt->cy = position.height;
lpw = (LPWORD) (lpdt + 1);
lpw = lpWordAlign(lpw);
*lpw++ = 0; // No menu
*lpw++ = 0; // Predefined dialog box class (by default)
LPWSTR lpwsz = (LPWSTR) lpw;
int nchar = MultiByteToWideChar(CP_ACP, 0, text.c_str(), -1, lpwsz, 50);
lpw += nchar;
}
//---------
LPWORD lpDwordAlign(LPWORD lpIn)
{
ULONG ul = (ULONG) lpIn;
ul += 3;
ul >>= 2;
ul <<= 2;
return (LPWORD) ul;
}
//---------
LPWORD lpWordAlign(LPWORD lpIn)
{
ULONG ul = (ULONG) lpIn;
ul++;
ul >>= 1;
ul <<= 1;
return (LPWORD) ul;
}
DialogCommandListenerList DialogCommandListeners;
EditBoxVariablesList EditBoxVariables;
HWND hwnd;
HWND parent;
LPDLGTEMPLATE lpdt;
LPWORD lpw;
int numcontrols;
unsigned long returncode;
};
//----------------------------------------
jNativeDialog::jNativeDialog() :
mPrivate(*new jNativeDialog::Private)
{
}
jNativeDialog::~jNativeDialog()
{
delete &mPrivate;
}
//todo: create native message box //::MessageBox(0, "Hi there", "title", MB_OK);
void jNativeDialog::SetWindowHandle(void* hwnd)
{
mPrivate.hwnd = (HWND) hwnd;
std::cout << "x=SetWindowHandle hwnd=" << mPrivate.hwnd << std::endl;
}
bool jNativeDialog::HandleDialogEvent(unsigned short id, unsigned int parm1, unsigned int parm2)
{
DialogCommandListenerList::iterator pos = mPrivate.DialogCommandListeners.find(id);
if (pos == mPrivate.DialogCommandListeners.end())
return false;
DialogCommandInfo info = pos->second;
(info.first)(info.second);
return true;
}
//----------------------------------------
void jNativeDialog::Create(const jWin& parent, const std::string& title, const jRect& rct)
{
mPrivate.init((HWND) parent.mHwnd);
mPrivate.DefDialog(title, rct);
}
//void jNativeDialog::AddEntry(const std::string& label, double& variable, int x, int y, int labelwidth, int entrywidth, int height);
//void jNativeDialog::AddEntry(const std::string& label, std::string& variable, int x, int y, int labelwidth, int entrywidth, int height);
void jNativeDialog::AddEdit(int defaultvalue, int& variable, const jRect& rct)
{
mPrivate.EditBoxVariables[mPrivate.numcontrols] = new EBVFunctorInt(variable);
std::stringstream buf;
buf << defaultvalue;
mPrivate.DefEdit(buf.str(), rct);
}
void jNativeDialog::AddEdit(double defaultvalue, double& variable, const jRect& rct)
{
mPrivate.EditBoxVariables[mPrivate.numcontrols] = new EBVFunctorDouble(variable);
std::stringstream buf;
buf << defaultvalue;
mPrivate.DefEdit(buf.str(), rct);
}
void jNativeDialog::AddButton(const std::string& label, DialogCallBack& cmd, const jRect& rct)
{
mPrivate.DialogCommandListeners[mPrivate.numcontrols] = make_pair(cmd, label);
mPrivate.DefButton(label, rct);
}
void jNativeDialog::AddLabel(const std::string& label, const jRect& rct)
{
mPrivate.DefLabel(label, rct);
}
//void jNativeDialog::SetSize(int width, int height);
void jNativeDialog::Close(unsigned long returncode)
{
std::cout << "x=Close hwnd=" << mPrivate.hwnd << std::endl;
//todo: get text from edit boxes
for (EditBoxVariablesList::iterator it = mPrivate.EditBoxVariables.begin(); it
!= mPrivate.EditBoxVariables.end(); it++)
{
char buf[100];
GetDlgItemText(mPrivate.hwnd, (*it).first, buf, sizeof(buf));
((*it).second)->Save(buf);
}
::EndDialog(mPrivate.hwnd, returncode);
mPrivate.returncode = returncode;
}
unsigned long jNativeDialog::Show()
{
mPrivate.lpdt->cdit = mPrivate.numcontrols; // Number of controls
//mWin.mHwnd = (HWND)::CreateDialogIndirectParam( //modeless
::DialogBoxIndirectParam(GetModuleHandle(NULL), mPrivate.lpdt, mPrivate.parent, DialogProc,
(WPARAM) this);
free(mPrivate.lpdt);
//::SetWindowLong((HWND) mWin.mHwnd, GWL_USERDATA, (LONG) this);
DWORD gle = GetLastError();
std::cout << "x=gle=" << gle << std::endl;
return mPrivate.returncode;
}
|
|
|
#pragma once
#include "jWin.h"
#include "jMenu.h"
#include "jRect.h"
#include "jICallBack.h"
#include <string>
//----------------------------------------
class jNativeWin
{
public:
virtual ~jNativeWin(void);
const jWin& GetWin() const
{
return mWin;
}
void ConvertToChildWindow();
void SetParent(const jWin& parent);
void SetSize(int x, int y, int width, int height);
jRect GetSize();
void Text(const std::string& s);
void Show();
void SetActive();
void Redraw();
void Close();
protected:
jNativeWin(void);
void CreateSkeletonWindow(const std::string& className);
jWin mWin;
};
//----------------------------------------
class jNativeDialog
{
public:
jNativeDialog();
~jNativeDialog();
void Create(const jWin& parent, const std::string& title, const jRect& rct);
// void Text(const std::string& s);
unsigned long Show();
// void AddEntry(const std::string& label, int& variable, int x, int y, int labelwidth,
// int entrywidth, int height);
void AddEdit(int defaultvalue, int& variable, const jRect& rct);
void AddEdit(double defaultvalue, double& variable, const jRect& rct);
void AddButton(const std::string& label, DialogCallBack& cmd, const jRect& rct);
void AddLabel(const std::string& label, const jRect& rct);
//void AddEntry(const std::string& label, double& variable, int x, int y, int labelwidth, int entrywidth, int height);
//void AddEntry(const std::string& label, std::string& variable, int x, int y, int labelwidth, int entrywidth, int height);
//void SetSize(int width, int height);
void Close(unsigned long returncode);
void HandleCommand(void* hwnd, short itemid); //todo: remove
bool HandleDialogEvent(unsigned short id, unsigned int parm1, unsigned int parm2);
void SetWindowHandle(void* hwnd);
private:
class Private;
Private& mPrivate;
};
//----------------------------------------
class jNativeFrameWin : public jNativeWin
{
public:
jNativeFrameWin();
void SetSize(int width, int height);
void CreateSkeletonWindow(const std::string& className);
long StartMessageLoop();
//todo: add typedef for menu id
void SetMenuCommandCallBack(short itemid, const std::string& name, MenuCallBack& fn);
void UpdateMenuCommandCallBack(short itemid, const std::string& newname);
void HandleMenuCommand(short itemid);
void AddOnPaintCallBack(PaintCallBack& cmd) const;
void Paint(jGraphics& g);
//todo: add typedef for id
//todo: rename PostEvent or AddGenericCallBack to be consistent
void PostEvent(unsigned short id, unsigned int parm1, unsigned parm2);
void AddGenericCallBack(unsigned short id, GenericCallBack& cmd) const;
void HandleGenericEvent(unsigned short id, unsigned int parm1, unsigned int parm2);
private:
class Private;
Private& mPrivate;
void CreateFrameWin(const std::string& className);
void RegisterWinClass(const std::string& className);
};
//----------------------------------------
class jNativeListBox : public jNativeWin
{
public:
void CreateSkeletonWindow();
void AddString(const std::string& s);
};
//----------------------------------------
class jNativeMenu
{
public:
explicit jNativeMenu(jNativeFrameWin& w);
~jNativeMenu();
void CreateDropDown(const std::string& name);
jMenu::MenuItem* CreateMenuItem(const std::string& name, MenuCallBack& fn);
jMenu::MenuItem* AddItem(const std::string& name, MenuCallBack& fn);
private:
class Private;
Private& mPrivate;
void AttachMenu();
void NullAttach();
};
//----------------------------------------
class jColor;
class jNativeGraphics
{
public:
explicit jNativeGraphics(unsigned long hdc);
~jNativeGraphics();
void Line(int x1, int y1, int x2, int y2);
void FillRect(const jColor& color, const jRect& rct);
void Text(const std::string& txt, const jRect& rct);
private:
class Private;
Private& mPrivate;
};
|
|
|
#pragma once
class jRect
{
public:
int x;
int y;
int width;
int height;
};
|
|
|
#pragma once
namespace TL
{
struct NullType
{
enum
{
Length = 0
};
};
template <typename T0, typename T1> struct TypeList
{
typedef T0 Head;
typedef T1 Tail;
enum
{
Length = 1 + Tail::Length
};
};
#define TYPELIST0() TL::NullType
#define TYPELIST1(T1) TL::TypeList<T1, TL::NullType >
#define TYPELIST2(T1, T2) TL::TypeList<T1, TYPELIST1(T2) >
#define TYPELIST3(T1, T2, T3) TL::TypeList<T1, TYPELIST2(T2, T3) >
//--- Length ------
template <typename TList> struct Length;
template <> struct Length<NullType>
{
enum
{
Value = 0
};
};
template <typename T0, typename T1> struct Length<TypeList<T0, T1> >
{
enum
{
Value = 1 + Length<T1>::Value
};
};
//--- TypeAt ------
template <class TList, unsigned int index, class OutOfBound = NullType> struct TypeAt;
template <class THead, class TTail, class OutOfBound> struct TypeAt<TypeList<THead, TTail> , 0,
OutOfBound>
{
typedef THead Type;
};
template <class THead, class TTail, unsigned int i, class OutOfBound> struct TypeAt<TypeList<
THead, TTail> , i, OutOfBound>
{
typedef typename TypeAt<TTail, i - 1>::Type Type;
};
template <unsigned int i, class OutOfBound> struct TypeAt<NullType, i, OutOfBound>
{
typedef OutOfBound Type;
};
}
|
|
|
#pragma once
class jWin
{
public:
void SetWin(void* hwnd)
{
mHwnd = hwnd;
}
private:
friend class jNativeFrameWin;
friend class jNativeWin;
friend class jNativeListBox;
friend class jNativeMenu;
friend class jNativeDialog;
void* mHwnd;
};
|
|
|
#pragma once
class jWin;
class jWinComponent
{
public:
virtual ~jWinComponent()
{
}
virtual void SetOwnerTo(const jWin& owner) = 0;
virtual void SetSize(int x, int y, int width, int height) = 0;
};
|