[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]
GUIさえ描ければあとはサンプルコードをmainファイルとして入れ替えて学習を進めることができます。
今回はWindowに様々な図形を描画しています。
[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]
GUIさえ描ければあとはサンプルコードをmainファイルとして入れ替えて学習を進めることができます。
今回はWindowに様々な図形を描画しています。
[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]
プロジェクトのディレクトリ構成は下図の通りです。
Makefile, CMakeLists.txtも載せておきます。
# コンパイラ
COMPILER = clang++
DEBUG = -g
# オプション
CPPFLAGS = $(shell fltk-config --use-gl --use-images --cxxflags ) -std=c++11
LDFLAGS = $(shell fltk-config --use-gl --use-images --ldflags ) -lc++
# includeパス(-I)
INCLUDE = -I./include -I/opt/homebrew/Cellar/libpng/1.6.37/include -I/opt/homebrew/Cellar/fltk/1.3.8/include \
-I/opt/homebrew/Cellar/opencv/4.5.5_2/include
# ライブラリ直接パス(-l)
LIBRARYD = -lpng16 -lz -lopencv_core -lopencv_imgcodecs -lopencv_highgui -lopencv_imgproc
# ライブラリパス(-L)
LIBRARY = -L/opt/homebrew/Cellar/jpeg/9e/lib -L/opt/homebrew/Cellar/libpng/1.6.37/lib \
-L/usr/local/lib -L/opt/homebrew/Cellar/opencv/4.5.5_2/lib
# ソースファイル
SRCDIR = ./src
SRCS = $(shell find $(SRCDIR) -type f)
# オブジェクトファイル
OBJDIR = ./obj
OBJS = $(addprefix $(OBJDIR), $(patsubst ./src%,%,$(SRCS:.cpp=.o)))
# 実行ファイル
TARGETDIR = ./bin
TARGET = PPPGui
# プロジェクト
PROJ = PPP02
# コンパイル
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(COMPILER) $(CPPFLAGS) $(INCLUDE) $(DEBUG) -o $@ -c $<
# appファイル作成関連
POSTBUILD = fltk-config --post
# ビルド:oファイルから実行ファイルとappファイル作成
$(TARGET):$(OBJS)
$(COMPILER) -o $(TARGETDIR)/$@ $(OBJS) $(LIBRARYD) $(LDFLAGS) $(LIBRARY)
cp $(TARGETDIR)/$(TARGET) ./app/$(TARGET)
cd ./app && $(POSTBUILD) $(TARGET)
mkdir ./app/$(TARGET).app/Contents/Resources
cp ./images/$(TARGET).icns ./app/$(TARGET).app/Contents/Resources
plutil -insert 'CFBundleIconFile' -string $(TARGET).icns ./app/$(TARGET).app/Contents/Info.plist
rm -f ./app/$(TARGET)
# ファイル削除
.PHONY:clean
clean:
rm -rf $(OBJS) $(TARGETDIR)/$(TARGET) $(TARGET).app $(SRCDIR)/.DS_Store ./app/*
# CMakeからappファイル作成
.PHONY : all
all:
rm -rf build/* $(SRCDIR)/.DS_Store
cd /Volumes/DATA_m1/code/cpp/projects/$(PROJ)/build && cmake .. && make
mkdir ./build/$(TARGET).app/Contents/Resources
cp ./images/$(TARGET).icns ./build/$(TARGET).app/Contents/Resources
plutil -replace 'CFBundleIconFile' -string "$(TARGET).icns" ./build/$(TARGET).app/Contents/Info.plist
# 自製Makefileから実行ファイルおよびappファイル作成
.PHONY:all2
all2: clean $(TARGET)
# 実行ファイルからappファイル作成(Info.plistが必要)
.PHONY : exetoapp
exetoapp:
mkdir $(TARGETDIR)/$(TARGET)
mkdir $(TARGETDIR)/$(TARGET)/Contents
mkdir $(TARGETDIR)/$(TARGET)/Contents/MacOS
mkdir $(TARGETDIR)/$(TARGET)/Contents/Resources
cp $(TARGETDIR)/$(TARGET).exe $(TARGETDIR)/$(TARGET)/Contents/MacOS
cp ./Info.plist $(TARGETDIR)/$(TARGET)/Contents
cp ./images/test.icns $(TARGETDIR)/$(TARGET)/Contents/Resources
plutil -replace 'CFBundleIconFile' -string "test.icns" $(TARGETDIR)/$(TARGET)/Contents/Info.plist
cmake_minimum_required(VERSION 3.1)
# Project
Project(PPPGui VERSION 1.0.0)
FIND_PACKAGE(FLTK REQUIRED)
FIND_PACKAGE(OpenGL REQUIRED)
find_library(COCOA Cocoa)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_VERBOSE_MAKEFILE ON)
# Info.plist
set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "")
set(MACOSX_BUNDLE_INFO_STRING "")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "")
# ファイル設定
file(GLOB SOURCE ./src/*.cpp ./include/*.h)
add_executable(${PROJECT_NAME}
MACOSX_BUNDLE
${SOURCE}
)
set(INCDIR ./include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/libpng/1.6.37/include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/fltk/1.3.8/include)
set(INCDIR ${INCDIR} /opt/homebrew/Cellar/jpeg/9e/include)
include_directories(${INCDIR})
set(LIBS dl)
set(LIBS ${LIBS} z pthread c++)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_forms.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_gl.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk_images.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/jpeg/9e/lib/libjpeg.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/libpng/1.6.37/lib/libpng.dylib)
set(LIBS ${LIBS} /opt/homebrew/Cellar/fltk/1.3.8/lib/libfltk.dylib)
set(LIBDIR /opt/homebrew/Cellar/jpeg/9e/lib)
set(LIBDIR ${LIBDIR} /opt/homebrew/Cellar/libpng/1.6.37/lib)
set(LIBDIR ${LIBDIR} /opt/homebrew/Cellar/fltk/1.3.8/lib)
link_directories(${LIBDIR})
target_link_libraries(${PROJECT_NAME}
${FLTK}
${OpenGL}
${LIBS}
${COCOA})
[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]
Guiファイルについてはincludeのところを修正しました。
std_lib_facilities.hはストラウストラップ氏のホームページに公開しています。
#ifndef GUI_GUARD
#define GUI_GUARD
#include "Point.h"
#include <FL/Fl_Widget.H>
#include "Window.h"
namespace Graph_lib {
typedef void* Address;
typedef void (*Callback)(Address,Address);
template<class W> W& reference_to(Address pw)
{
return *static_cast<W*>(pw);
}
class Widget {
public:
Widget(Point xy, int w, int h, const string& s, Callback cb)
:loc(xy), width(w), height(h), label(s), do_it(cb)
{ }
virtual void move(int dx,int dy) { hide(); pw->position(loc.x+=dx, loc.y+=dy); show(); }
virtual void hide() { pw->hide(); }
virtual void show() { pw->show(); }
virtual void attach(Window&) = 0;
Point loc;
int width;
int height;
string label;
Callback do_it;
virtual ~Widget() { }
Gui.h, Gui.cpp 全ソースコード
Window.h, Window.cpp 全ソースコード
Simple_window.h, Point.h, main.cpp 全ソースコード
[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]
最もボリュームがあるのがGraphファイルです。
FLTK1.1に対応した内容なのでFLTK1.3.8が使えるように書き換えました。コードがコメントアウトになっているところは復活させるかもしれないので残しておきました。
C++では自前で用意すべきerror関数がないのはご愛嬌でしょうか。
あれだけの多作家ですからコードのメンテナンスができていないところに人間味を感じます。ただ絶版にはなっていないので出版社含めちゃんとして欲しいですね。
2022/6/17追記:
ストラウストラップ氏HPのsupport code for PPP2 (tar ball)にfltk.hを含むtarがあります。fltk.hはFLTKの各種ヘッダファイルをグループ化したものです。FLTK1.1でもFLTK1.3.8でも同じように使えるはずです。
#ifndef GRAPH_GUARD
#define GRAPH_GUARD 1
#include "Point.h"
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <iostream>
#include <stdio.h>
#include <vector>
#include <cmath> // コメントアウトになっていた
using std::string; using std::initializer_list;
using std::vector; using std::cout;
// このエラー関数が存在していなかった
void error (const char* message) ;
namespace Graph_lib {
#undef major
#undef minor
struct Color {
enum Color_type {
red=FL_RED, blue=FL_BLUE, green=FL_GREEN,
yellow=FL_YELLOW, white=FL_WHITE, black=FL_BLACK,
magenta=FL_MAGENTA, cyan=FL_CYAN, dark_red=FL_DARK_RED,
dark_green=FL_DARK_GREEN, dark_yellow=FL_DARK_YELLOW, dark_blue=FL_DARK_BLUE,
dark_magenta=FL_DARK_MAGENTA, dark_cyan=FL_DARK_CYAN
};
enum Transparency { invisible = 0, visible=255 };
Color(Color_type cc) :c(Fl_Color(cc)), v(visible) { }
Color(Color_type cc, Transparency vv) :c(Fl_Color(cc)), v(vv) { }
Color(int cc) :c(Fl_Color(cc)), v(visible) { }
Color(Transparency vv) :c(Fl_Color()), v(vv) { }
int as_int() const { return c; }
char visibility() const { return v; }
void set_visibility(Transparency vv) { v=vv; }
private:
unsigned char v;
Fl_Color c;
};
[M1 Mac, Big Sur 11.6.7, FLTK 1.3.8, clang 13.0.0, no IDE]
ストラウストラップ氏の名著”プログラミング入門”(原書初版2008年)のGUIソースコード(日本語版P362)が現在の環境では動かないため関連ファイルを修正しました。
ヘッダファイル等はストラウストラップ氏のホームページから入手できます。こちらの方に手を入れました。
50個ほどのエラーを直していく気の遠くなるような作業でしたが、何とか復元できました。S氏はFLTKのインストールと設定は経験者でも難しいと説明しています。確かに普段使いしている私もライブラリの選択などで手間取りましたから、かなりの方が苦労していると思います。
ソースコードは次回以降アップします。
Drag & Dropの実装はApple公式ドキュメントのコードが古くなっていることもあり一筋縄ではいきません。一つ一つ解決していきます。
NSString *filePath1, *filePath2; // Assume these exist
- (void)mouseDown:(NSEvent *)theEvent
{
NSImage *dragImage;
NSPoint dragPosition;
// Write data to the pasteboard
NSArray *fileList = [NSArray arrayWithObjects:filePath1, filePath2, nil];
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
[pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
owner:nil];
[pboard setPropertyList:fileList forType:NSFilenamesPboardType];
// Start the drag operation
dragImage = [[NSWorkspace sharedWorkspace] iconForFile:filePath1];
dragPosition = [self convertPoint:[theEvent locationInWindow]
fromView:nil];
dragPosition.x -= 16;
dragPosition.y -= 16;
[self dragImage:dragImage
at:dragPosition
offset:NSZeroSize
event:theEvent
pasteboard:pboard
source:self
slideBack:YES];
}
警告1
/XlsxConvertor.mm:292:61: warning:
'NSDragPboard' is deprecated: first deprecated in macOS 10.13
[-Wdeprecated-declarations]
NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
^~~~~~~~~~~~
NSPasteboardNameDrag
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSPasteboard.h:338:32: note: 'NSDragPboard' has been explicitly marked deprecated here
APPKIT_EXTERN NSPasteboardName NSDragPboard API_DEPRECATED_WITH_REPLACEMENT("NSPasteboardNameDrag", macos(10.0,10.13));
^
警告2
/XlsxConvertor.mm:293:51: warning: 'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14 - Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead [-Wdeprecated-declarations]
[pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSPasteboard.h:312:32: note:
'NSFilenamesPboardType' has been explicitly marked deprecated here
APPKIT_EXTERN NSPasteboardType NSFilenamesPboardType API_DEPRECATED("Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead", macos(10.0,10.14));
^
警告3
/XlsxConvertor.mm:295:46: warning:
'NSFilenamesPboardType' is deprecated: first deprecated in macOS 10.14
- Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead [-Wdeprecated-declarations]
[pboard setPropertyList:fileList forType:NSFilenamesPboardType];
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/AppKit.framework/Headers/NSPasteboard.h:312:32: note:
'NSFilenamesPboardType' has been explicitly marked deprecated here
APPKIT_EXTERN NSPasteboardType NSFilenamesPboardType API_DEPRECATED("Create multiple pasteboard items with NSPasteboardTypeFileURL or kUTTypeFileURL instead", macos(10.0,10.14));
^
警告4
/XlsxConvertor.mm:299:26: warning: instance method '-convertPoint:fromView:' not found (return type defaults to 'id') [-Wobjc-method-access]
dragPosition = [self convertPoint:[theEvent locationInWindow]
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
注意1
/XlsxConvertor.mm:7:12: note: receiver is instance of class declared here
@interface Window : NSWindow {
^
エラー1
/XlsxConvertor.mm:299:18: error: no viable overloaded '='
dragPosition = [self convertPoint:[theEvent locationInWindow]
~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/CoreGraphics.framework/Headers/CGGeometry.h:20:1: note:
candidate function (the implicit copy assignment operator) not viable: no known conversion from 'id' to 'const CGPoint' for 1st argument
CGPoint {
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.1.sdk/System/Library/Frameworks/CoreGraphics.framework/Headers/CGGeometry.h:20:1: note:
candidate function (the implicit move assignment operator) not viable: no known conversion from 'id' to 'CGPoint' for 1st argument
4 warnings and 1 error generated.