mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	| @@ -22,8 +22,6 @@ | ||||
| # include "hfs.h" | ||||
| # include "apple.h" | ||||
|  | ||||
| extern int errno; | ||||
|  | ||||
| # define ERROR(code, str)  \ | ||||
|     do { hfs_error = (str), errno = (code); goto fail; } while (0) | ||||
|  | ||||
|   | ||||
| @@ -24,6 +24,7 @@ LIBFLUXENGINE_SRCS = \ | ||||
| 	lib/fluxsource/hardwarefluxsource.cc \ | ||||
| 	lib/fluxsource/kryoflux.cc \ | ||||
| 	lib/fluxsource/kryofluxfluxsource.cc \ | ||||
| 	lib/fluxsource/memoryfluxsource.cc \ | ||||
| 	lib/fluxsource/scpfluxsource.cc \ | ||||
| 	lib/fluxsource/testpatternfluxsource.cc \ | ||||
| 	lib/globals.cc \ | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
| #include "flags.h" | ||||
|  | ||||
| class CwfFluxSourceProto; | ||||
| class DiskFlux; | ||||
| class EraseFluxSourceProto; | ||||
| class Fl2FluxSourceProto; | ||||
| class FluxSourceProto; | ||||
| @@ -38,6 +39,8 @@ private: | ||||
|     static std::unique_ptr<FluxSource> createTestPatternFluxSource(const TestPatternFluxSourceProto& config); | ||||
|  | ||||
| public: | ||||
|     static std::unique_ptr<FluxSource> createMemoryFluxSource(const DiskFlux& flux); | ||||
|  | ||||
|     static std::unique_ptr<FluxSource> create(const FluxSourceProto& spec); | ||||
| 	static void updateConfigForFilename(FluxSourceProto* proto, const std::string& filename); | ||||
|  | ||||
|   | ||||
| @@ -58,6 +58,7 @@ public: | ||||
|         _hardSectorThreshold = 0; | ||||
| 		if (_oneRevolution == 0) | ||||
| 		{ | ||||
| 			Logger() << BeginOperationLogMessage{"Measuring drive rotational speed"}; | ||||
| 			do | ||||
| 			{ | ||||
| 				_oneRevolution = | ||||
| @@ -71,6 +72,7 @@ public: | ||||
| 				retries--; | ||||
| 			} while ((_oneRevolution == 0) && (retries > 0)); | ||||
| 			config.mutable_drive()->set_rotational_period_ms(_oneRevolution / 1e6); | ||||
| 			Logger() << EndOperationLogMessage{}; | ||||
| 		} | ||||
|  | ||||
|         if (_oneRevolution == 0) | ||||
|   | ||||
							
								
								
									
										75
									
								
								lib/fluxsource/memoryfluxsource.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								lib/fluxsource/memoryfluxsource.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,75 @@ | ||||
| #include "lib/globals.h" | ||||
| #include "lib/fluxmap.h" | ||||
| #include "lib/flux.h" | ||||
| #include "lib/fluxsource/fluxsource.h" | ||||
| #include "lib/fluxmap.h" | ||||
| #include <fmt/format.h> | ||||
| #include <fstream> | ||||
|  | ||||
| class MemoryFluxSourceIterator : public FluxSourceIterator | ||||
| { | ||||
| public: | ||||
| 	MemoryFluxSourceIterator(const TrackFlux& track): | ||||
| 		_track(track) | ||||
| 	{} | ||||
|  | ||||
| 	bool hasNext() const override | ||||
| 	{ | ||||
| 		return _count < _track.trackDatas.size(); | ||||
| 	} | ||||
|  | ||||
| 	std::unique_ptr<const Fluxmap> next() override | ||||
| 	{ | ||||
| 		auto bytes = _track.trackDatas[_count]->fluxmap->rawBytes(); | ||||
| 		_count++; | ||||
| 		return std::make_unique<Fluxmap>(bytes); | ||||
| 	} | ||||
|  | ||||
| private: | ||||
| 	const TrackFlux& _track; | ||||
| 	int _count = 0; | ||||
| }; | ||||
|  | ||||
| class EmptyFluxSourceIterator : public FluxSourceIterator | ||||
| { | ||||
| 	bool hasNext() const override | ||||
| 	{ | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	std::unique_ptr<const Fluxmap> next() override | ||||
| 	{ | ||||
| 		Error() << "no flux to read"; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class MemoryFluxSource : public FluxSource | ||||
| { | ||||
| public: | ||||
|     MemoryFluxSource(const DiskFlux& flux): _flux(flux) | ||||
|     { | ||||
|     } | ||||
|  | ||||
| public: | ||||
|     std::unique_ptr<FluxSourceIterator> readFlux(int track, int head) override | ||||
|     { | ||||
|         for (const auto& trackFlux : _flux.tracks) | ||||
|         { | ||||
| 			if ((trackFlux->location.physicalTrack == track) && (trackFlux->location.head == head)) | ||||
| 				return std::make_unique<MemoryFluxSourceIterator>(*trackFlux); | ||||
|         } | ||||
|  | ||||
|         return std::make_unique<EmptyFluxSourceIterator>(); | ||||
|     } | ||||
|  | ||||
|     void recalibrate() {} | ||||
|  | ||||
| private: | ||||
| 	const DiskFlux& _flux; | ||||
| }; | ||||
|  | ||||
| std::unique_ptr<FluxSource> FluxSource::createMemoryFluxSource(const DiskFlux& flux) | ||||
| { | ||||
| 	return std::make_unique<MemoryFluxSource>(flux); | ||||
| } | ||||
|  | ||||
| @@ -83,8 +83,10 @@ std::string Logger::toString(const AnyLogMessage& message) | ||||
|                 std::set<std::shared_ptr<const Record>> rawRecords; | ||||
|                 for (const auto& trackDataFlux : track.trackDatas) | ||||
|                 { | ||||
|                     rawSectors.insert(trackDataFlux->sectors.begin(), trackDataFlux->sectors.end()); | ||||
|                     rawRecords.insert(trackDataFlux->records.begin(), trackDataFlux->records.end()); | ||||
|                     rawSectors.insert(trackDataFlux->sectors.begin(), | ||||
|                         trackDataFlux->sectors.end()); | ||||
|                     rawRecords.insert(trackDataFlux->records.begin(), | ||||
|                         trackDataFlux->records.end()); | ||||
|                 } | ||||
|  | ||||
|                 nanoseconds_t clock = 0; | ||||
| @@ -136,6 +138,21 @@ std::string Logger::toString(const AnyLogMessage& message) | ||||
|                 stream << fmt::format("{} bytes decoded\n", size); | ||||
|             }, | ||||
|  | ||||
|             /* Large-scale operation start. */ | ||||
|             [&](const BeginOperationLogMessage& m) | ||||
|             { | ||||
|             }, | ||||
|  | ||||
|             /* Large-scale operation end. */ | ||||
|             [&](const EndOperationLogMessage& m) | ||||
|             { | ||||
|             }, | ||||
|  | ||||
|             /* Large-scale operation progress. */ | ||||
|             [&](const OperationProgressLogMessage& m) | ||||
|             { | ||||
|             }, | ||||
|  | ||||
|             /* Generic text message */ | ||||
|             [&](const std::string& s) | ||||
|             { | ||||
|   | ||||
							
								
								
									
										40
									
								
								lib/logger.h
									
									
									
									
									
								
							
							
						
						
									
										40
									
								
								lib/logger.h
									
									
									
									
									
								
							| @@ -10,7 +10,11 @@ class Sector; | ||||
|  | ||||
| struct ErrorLogMessage | ||||
| { | ||||
| 	std::string message; | ||||
|     std::string message; | ||||
| }; | ||||
|  | ||||
| struct EmergencyStopMessage | ||||
| { | ||||
| }; | ||||
|  | ||||
| struct BeginSpeedOperationLogMessage | ||||
| @@ -29,7 +33,7 @@ struct TrackReadLogMessage | ||||
|  | ||||
| struct DiskReadLogMessage | ||||
| { | ||||
| 	std::shared_ptr<const DiskFlux> disk; | ||||
|     std::shared_ptr<const DiskFlux> disk; | ||||
| }; | ||||
|  | ||||
| struct BeginReadOperationLogMessage | ||||
| @@ -40,8 +44,8 @@ struct BeginReadOperationLogMessage | ||||
|  | ||||
| struct EndReadOperationLogMessage | ||||
| { | ||||
| 	std::shared_ptr<const TrackDataFlux> trackDataFlux; | ||||
| 	std::set<std::shared_ptr<const Sector>> sectors; | ||||
|     std::shared_ptr<const TrackDataFlux> trackDataFlux; | ||||
|     std::set<std::shared_ptr<const Sector>> sectors; | ||||
| }; | ||||
|  | ||||
| struct BeginWriteOperationLogMessage | ||||
| @@ -54,19 +58,37 @@ struct EndWriteOperationLogMessage | ||||
| { | ||||
| }; | ||||
|  | ||||
| struct BeginOperationLogMessage | ||||
| { | ||||
|     std::string message; | ||||
| }; | ||||
|  | ||||
| struct EndOperationLogMessage | ||||
| { | ||||
|     std::string message; | ||||
| }; | ||||
|  | ||||
| struct OperationProgressLogMessage | ||||
| { | ||||
|     unsigned progress; | ||||
| }; | ||||
|  | ||||
| class TrackFlux; | ||||
|  | ||||
| typedef std::variant< | ||||
| 	std::string, | ||||
| 	ErrorLogMessage, | ||||
| typedef std::variant<std::string, | ||||
|     ErrorLogMessage, | ||||
|     EmergencyStopMessage, | ||||
|     TrackReadLogMessage, | ||||
| 	DiskReadLogMessage, | ||||
|     DiskReadLogMessage, | ||||
|     BeginSpeedOperationLogMessage, | ||||
|     EndSpeedOperationLogMessage, | ||||
|     BeginReadOperationLogMessage, | ||||
|     EndReadOperationLogMessage, | ||||
|     BeginWriteOperationLogMessage, | ||||
|     EndWriteOperationLogMessage> | ||||
|     EndWriteOperationLogMessage, | ||||
|     BeginOperationLogMessage, | ||||
|     EndOperationLogMessage, | ||||
|     OperationProgressLogMessage> | ||||
|     AnyLogMessage; | ||||
|  | ||||
| class Logger | ||||
|   | ||||
| @@ -187,8 +187,17 @@ void writeTracks(FluxSink& fluxSink, | ||||
|         producer, | ||||
|     std::function<bool(const Location& location)> verifier) | ||||
| { | ||||
|     for (const auto& location : Mapper::computeLocations()) | ||||
|     Logger() << BeginOperationLogMessage{"Encoding and writing to disk"}; | ||||
|  | ||||
|     auto locations = Mapper::computeLocations(); | ||||
|  | ||||
|     int index = 0; | ||||
|     for (const auto& location : locations) | ||||
|     { | ||||
|         Logger() << OperationProgressLogMessage{ | ||||
|             index * 100 / (unsigned)locations.size()}; | ||||
|         index++; | ||||
|  | ||||
|         testForEmergencyStop(); | ||||
|  | ||||
|         int retriesRemaining = config.decoder().retries(); | ||||
| @@ -237,6 +246,8 @@ void writeTracks(FluxSink& fluxSink, | ||||
|             retriesRemaining--; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     Logger() << EndOperationLogMessage{"Write complete"}; | ||||
| } | ||||
|  | ||||
| static bool dontVerify(const Location&) | ||||
| @@ -285,30 +296,38 @@ void writeTracksAndVerify(FluxSink& fluxSink, | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
| 			Image wanted; | ||||
| 			for (const auto& sector : encoder.collectSectors(location, image)) | ||||
| 				wanted.put(sector->logicalTrack, sector->logicalSide, sector->logicalSector)->data = sector->data; | ||||
|             Image wanted; | ||||
|             for (const auto& sector : encoder.collectSectors(location, image)) | ||||
|                 wanted | ||||
|                     .put(sector->logicalTrack, | ||||
|                         sector->logicalSide, | ||||
|                         sector->logicalSector) | ||||
|                     ->data = sector->data; | ||||
|  | ||||
| 			for (const auto& sector : trackFlux->sectors) | ||||
| 			{ | ||||
| 				const auto s = wanted.get(sector->logicalTrack, sector->logicalSide, sector->logicalSector); | ||||
| 				if (!s) | ||||
| 				{ | ||||
| 					Logger() << "spurious sector on verify"; | ||||
| 					return false; | ||||
| 				} | ||||
| 				if (s->data != sector->data.slice(0, s->data.size())) | ||||
| 				{ | ||||
| 					Logger() << "data mismatch on verify"; | ||||
| 					return false; | ||||
| 				} | ||||
| 				wanted.erase(sector->logicalTrack, sector->logicalSide, sector->logicalSector); | ||||
| 			} | ||||
| 			if (!wanted.empty()) | ||||
| 			{ | ||||
| 				Logger() << "missing sector on verify"; | ||||
| 				return false; | ||||
| 			} | ||||
|             for (const auto& sector : trackFlux->sectors) | ||||
|             { | ||||
|                 const auto s = wanted.get(sector->logicalTrack, | ||||
|                     sector->logicalSide, | ||||
|                     sector->logicalSector); | ||||
|                 if (!s) | ||||
|                 { | ||||
|                     Logger() << "spurious sector on verify"; | ||||
|                     return false; | ||||
|                 } | ||||
|                 if (s->data != sector->data.slice(0, s->data.size())) | ||||
|                 { | ||||
|                     Logger() << "data mismatch on verify"; | ||||
|                     return false; | ||||
|                 } | ||||
|                 wanted.erase(sector->logicalTrack, | ||||
|                     sector->logicalSide, | ||||
|                     sector->logicalSector); | ||||
|             } | ||||
|             if (!wanted.empty()) | ||||
|             { | ||||
|                 Logger() << "missing sector on verify"; | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
| @@ -319,14 +338,14 @@ void writeDiskCommand(const Image& image, | ||||
|     AbstractDecoder* decoder, | ||||
|     FluxSource* fluxSource) | ||||
| { | ||||
| 	const Image* imagep = ℑ | ||||
| 	std::unique_ptr<const Image> remapped; | ||||
|     const Image* imagep = ℑ | ||||
|     std::unique_ptr<const Image> remapped; | ||||
|     if (config.has_sector_mapping()) | ||||
| 	{ | ||||
|     { | ||||
|         remapped = Mapper::remapSectorsLogicalToPhysical( | ||||
|             image, config.sector_mapping()); | ||||
| 		imagep = &*remapped; | ||||
| 	} | ||||
|         imagep = &*remapped; | ||||
|     } | ||||
|  | ||||
|     if (fluxSource && decoder) | ||||
|         writeTracksAndVerify(fluxSink, encoder, *fluxSource, *decoder, *imagep); | ||||
| @@ -346,9 +365,8 @@ void writeRawDiskCommand(FluxSource& fluxSource, FluxSink& fluxSink) | ||||
|         dontVerify); | ||||
| } | ||||
|  | ||||
| std::shared_ptr<TrackFlux> readAndDecodeTrack(FluxSource& fluxSource, | ||||
|     AbstractDecoder& decoder, | ||||
|     const Location& location) | ||||
| std::shared_ptr<TrackFlux> readAndDecodeTrack( | ||||
|     FluxSource& fluxSource, AbstractDecoder& decoder, const Location& location) | ||||
| { | ||||
|     auto trackFlux = std::make_shared<TrackFlux>(); | ||||
|     trackFlux->location = location; | ||||
| @@ -378,7 +396,7 @@ std::shared_ptr<TrackFlux> readAndDecodeTrack(FluxSource& fluxSource, | ||||
|         retriesRemaining--; | ||||
|     } | ||||
|  | ||||
| 	return trackFlux; | ||||
|     return trackFlux; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<const DiskFlux> readDiskCommand( | ||||
| @@ -390,12 +408,18 @@ std::shared_ptr<const DiskFlux> readDiskCommand( | ||||
|  | ||||
|     auto diskflux = std::make_shared<DiskFlux>(); | ||||
|  | ||||
|     for (const auto& location : Mapper::computeLocations()) | ||||
|     Logger() << BeginOperationLogMessage{"Reading and decoding disk"}; | ||||
|     auto locations = Mapper::computeLocations(); | ||||
|     unsigned index = 0; | ||||
|     for (const auto& location : locations) | ||||
|     { | ||||
|         Logger() << OperationProgressLogMessage{ | ||||
|             index * 100 / (unsigned)locations.size()}; | ||||
|         index++; | ||||
|  | ||||
|         testForEmergencyStop(); | ||||
|  | ||||
|         auto trackFlux = readAndDecodeTrack( | ||||
|             fluxSource, decoder, location); | ||||
|         auto trackFlux = readAndDecodeTrack(fluxSource, decoder, location); | ||||
|         diskflux->tracks.push_back(trackFlux); | ||||
|  | ||||
|         if (outputFluxSink) | ||||
| @@ -478,6 +502,7 @@ std::shared_ptr<const DiskFlux> readDiskCommand( | ||||
|  | ||||
|     /* diskflux can't be modified below this point. */ | ||||
|     Logger() << DiskReadLogMessage{diskflux}; | ||||
|     Logger() << EndOperationLogMessage{"Read complete"}; | ||||
|     return diskflux; | ||||
| } | ||||
|  | ||||
| @@ -494,10 +519,20 @@ void readDiskCommand( | ||||
|  | ||||
| void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink) | ||||
| { | ||||
|     for (unsigned track : iterate(config.tracks())) | ||||
|     Logger() << BeginOperationLogMessage{"Performing raw read of disk"}; | ||||
|  | ||||
|     auto tracks = iterate(config.tracks()); | ||||
|     auto heads = iterate(config.heads()); | ||||
|     unsigned locations = tracks.size() * heads.size(); | ||||
|  | ||||
|     unsigned index = 0; | ||||
|     for (unsigned track : tracks) | ||||
|     { | ||||
|         for (unsigned head : iterate(config.heads())) | ||||
|         for (unsigned head : heads) | ||||
|         { | ||||
|             Logger() << OperationProgressLogMessage{index * 100 / locations}; | ||||
|             index++; | ||||
|  | ||||
|             testForEmergencyStop(); | ||||
|             auto fluxSourceIterator = fluxsource.readFlux(track, head); | ||||
|  | ||||
| @@ -511,6 +546,8 @@ void rawReadDiskCommand(FluxSource& fluxsource, FluxSink& fluxsink) | ||||
|             fluxsink.writeFlux(track, head, *fluxmap); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     Logger() << EndOperationLogMessage{"Raw read complete"}; | ||||
| } | ||||
|  | ||||
| void fillBitmapTo(std::vector<bool>& bitmap, | ||||
|   | ||||
							
								
								
									
										94
									
								
								lib/utils.cc
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								lib/utils.cc
									
									
									
									
									
								
							| @@ -34,6 +34,20 @@ std::string join( | ||||
|     } | ||||
| } | ||||
|  | ||||
| std::vector<std::string> split(const std::string& string, char separator) | ||||
| { | ||||
|     std::vector<std::string> result; | ||||
|     std::stringstream ss(string); | ||||
|     std::string item; | ||||
|  | ||||
|     while (std::getline(ss, item, separator)) | ||||
|     { | ||||
|         result.push_back(item); | ||||
|     } | ||||
|  | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| bool beginsWith(const std::string& value, const std::string& ending) | ||||
| { | ||||
|     if (ending.size() > value.size()) | ||||
| @@ -98,61 +112,60 @@ void testForEmergencyStop() | ||||
|  | ||||
| std::string toIso8601(time_t t) | ||||
| { | ||||
| 	auto* tm = std::gmtime(&t); | ||||
|     auto* tm = std::gmtime(&t); | ||||
|  | ||||
| 	std::stringstream ss; | ||||
| 	ss << std::put_time(tm, "%FT%T%z"); | ||||
| 	return ss.str(); | ||||
|     std::stringstream ss; | ||||
|     ss << std::put_time(tm, "%FT%T%z"); | ||||
|     return ss.str(); | ||||
| } | ||||
|  | ||||
| std::string quote(const std::string& s) | ||||
| { | ||||
| 	bool spaces = s.find(' ') != std::string::npos; | ||||
| 	if (!spaces | ||||
| 		&& (s.find('\\') == std::string::npos) | ||||
| 		&& (s.find('\'') == std::string::npos) | ||||
| 		&& (s.find('"') == std::string::npos)) | ||||
| 		return s; | ||||
|     bool spaces = s.find(' ') != std::string::npos; | ||||
|     if (!spaces && (s.find('\\') == std::string::npos) && | ||||
|         (s.find('\'') == std::string::npos) && | ||||
|         (s.find('"') == std::string::npos)) | ||||
|         return s; | ||||
|  | ||||
| 	std::stringstream ss; | ||||
| 	if (spaces) | ||||
| 		ss << '"'; | ||||
|     std::stringstream ss; | ||||
|     if (spaces) | ||||
|         ss << '"'; | ||||
|  | ||||
| 	for (char c : s) | ||||
| 	{ | ||||
| 		if ((c == '\\') || (c == '\"') || (c == '!')) | ||||
| 			ss << '\\'; | ||||
| 		ss << (char)c; | ||||
| 	} | ||||
|     for (char c : s) | ||||
|     { | ||||
|         if ((c == '\\') || (c == '\"') || (c == '!')) | ||||
|             ss << '\\'; | ||||
|         ss << (char)c; | ||||
|     } | ||||
|  | ||||
| 	if (spaces) | ||||
| 		ss << '"'; | ||||
| 	return ss.str(); | ||||
|     if (spaces) | ||||
|         ss << '"'; | ||||
|     return ss.str(); | ||||
| } | ||||
|  | ||||
| std::string unhex(const std::string& s) | ||||
| { | ||||
| 	std::stringstream sin(s); | ||||
| 	std::stringstream sout; | ||||
|     std::stringstream sin(s); | ||||
|     std::stringstream sout; | ||||
|  | ||||
| 	for (;;) | ||||
| 	{ | ||||
| 		int c = sin.get(); | ||||
| 		if (c == -1) | ||||
| 			break; | ||||
| 		if (c == '%') | ||||
| 		{ | ||||
| 			char buf[3]; | ||||
| 			buf[0] = sin.get(); | ||||
| 			buf[1] = sin.get(); | ||||
| 			buf[2] = 0; | ||||
|     for (;;) | ||||
|     { | ||||
|         int c = sin.get(); | ||||
|         if (c == -1) | ||||
|             break; | ||||
|         if (c == '%') | ||||
|         { | ||||
|             char buf[3]; | ||||
|             buf[0] = sin.get(); | ||||
|             buf[1] = sin.get(); | ||||
|             buf[2] = 0; | ||||
|  | ||||
| 			c = std::stoul(buf, nullptr, 16); | ||||
| 		} | ||||
| 		sout << (char)c; | ||||
| 	} | ||||
|             c = std::stoul(buf, nullptr, 16); | ||||
|         } | ||||
|         sout << (char)c; | ||||
|     } | ||||
|  | ||||
| 	return sout.str(); | ||||
|     return sout.str(); | ||||
| } | ||||
|  | ||||
| std::string tohex(const std::string& s) | ||||
| @@ -169,4 +182,3 @@ std::string tohex(const std::string& s) | ||||
|  | ||||
|     return ss.str(); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										10
									
								
								lib/utils.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								lib/utils.h
									
									
									
									
									
								
							| @@ -3,7 +3,10 @@ | ||||
|  | ||||
| #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) | ||||
|  | ||||
| extern std::string join(const std::vector<std::string>& values, const std::string& separator); | ||||
| extern std::string join( | ||||
|     const std::vector<std::string>& values, const std::string& separator); | ||||
| extern std::vector<std::string> split( | ||||
|     const std::string& string, char separator); | ||||
| extern bool beginsWith(const std::string& value, const std::string& beginning); | ||||
| extern bool endsWith(const std::string& value, const std::string& ending); | ||||
| extern std::string leftTrimWhitespace(std::string value); | ||||
| @@ -19,8 +22,9 @@ extern std::string tohex(const std::string& s); | ||||
|  */ | ||||
|  | ||||
| extern bool emergencyStop; | ||||
| class EmergencyStopException {}; | ||||
| class EmergencyStopException | ||||
| { | ||||
| }; | ||||
| extern void testForEmergencyStop(); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| comment: 'Commodore 1541 common settings' | ||||
| is_extension: true | ||||
|  | ||||
| image_reader { | ||||
| 	filename: "commodore1541.d64" | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| comment: 'DVK MX common settings' | ||||
| is_extension: true | ||||
|  | ||||
| image_writer { | ||||
| 	filename: "mx.img" | ||||
|   | ||||
| @@ -1,12 +1,14 @@ | ||||
| ifneq ($(shell $(WX_CONFIG) --version),) | ||||
|  | ||||
| FLUXENGINE_GUI_SRCS = \ | ||||
| 	src/gui/customstatusbar.cc \ | ||||
| 	src/gui/fluxviewercontrol.cc \ | ||||
| 	src/gui/fluxviewerwindow.cc \ | ||||
| 	src/gui/hexviewerwindow.cc \ | ||||
| 	src/gui/layout.cpp \ | ||||
| 	src/gui/main.cc \ | ||||
| 	src/gui/mainwindow.cc \ | ||||
| 	src/gui/texteditorwindow.cc \ | ||||
| 	src/gui/textviewerwindow.cc \ | ||||
| 	src/gui/visualisationcontrol.cc \ | ||||
|   | ||||
| FLUXENGINE_GUI_OBJS = \ | ||||
| @@ -15,9 +17,9 @@ FLUXENGINE_GUI_OBJS = \ | ||||
| 	) | ||||
| OBJS += $(FLUXENGINE_GUI_OBJS) | ||||
| $(FLUXENGINE_GUI_SRCS): | $(PROTO_HDRS) | ||||
| $(FLUXENGINE_GUI_OBJS): CFLAGS += $(shell $(WX_CONFIG) --cxxflags core base) | ||||
| $(FLUXENGINE_GUI_OBJS): CFLAGS += $(shell $(WX_CONFIG) --cxxflags core base adv) | ||||
| FLUXENGINE_GUI_BIN = $(OBJDIR)/fluxengine-gui.exe | ||||
| $(FLUXENGINE_GUI_BIN): LDFLAGS += $(shell $(WX_CONFIG) --libs core base) | ||||
| $(FLUXENGINE_GUI_BIN): LDFLAGS += $(shell $(WX_CONFIG) --libs core base adv) | ||||
| $(FLUXENGINE_GUI_BIN): $(FLUXENGINE_GUI_OBJS) | ||||
|  | ||||
| $(call use-pkgconfig, $(FLUXENGINE_GUI_BIN), $(FLUXENGINE_GUI_OBJS), fmt) | ||||
|   | ||||
							
								
								
									
										108
									
								
								src/gui/customstatusbar.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/gui/customstatusbar.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| #include "lib/globals.h" | ||||
| #include "gui.h" | ||||
| #include "customstatusbar.h" | ||||
| #include <wx/artprov.h> | ||||
| #include <fmt/format.h> | ||||
|  | ||||
| // clang-format off | ||||
| BEGIN_EVENT_TABLE(CustomStatusBar, wxStatusBar) | ||||
| 	EVT_SIZE(CustomStatusBar::OnSize) | ||||
| END_EVENT_TABLE() | ||||
| // clang-format on | ||||
|  | ||||
| wxDEFINE_EVENT(PROGRESSBAR_STOP_EVENT, wxCommandEvent); | ||||
|  | ||||
| CustomStatusBar::CustomStatusBar(wxWindow* parent, wxWindowID id): | ||||
|     wxStatusBar(parent, id) | ||||
| { | ||||
|     SetFieldsCount(4); | ||||
|  | ||||
|     static const int widths[] = {-1, 200, 100, 20}; | ||||
|     SetStatusWidths(4, widths); | ||||
|  | ||||
|     static const int styles[] = { wxSB_FLAT, wxSB_FLAT, wxSB_FLAT, wxSB_FLAT }; | ||||
|     SetStatusStyles(4, styles); | ||||
|  | ||||
|     _progressBar.reset(new wxGauge(this, | ||||
|         wxID_ANY, | ||||
|         100, | ||||
|         wxDefaultPosition, | ||||
|         wxDefaultSize, | ||||
|         wxGA_HORIZONTAL | wxGA_SMOOTH)); | ||||
|  | ||||
|     _stopButton.reset(new wxButton(this, | ||||
|         wxID_ANY, | ||||
|         "Stop", | ||||
|         wxDefaultPosition, | ||||
|         wxDefaultSize, | ||||
|         wxBU_EXACTFIT)); | ||||
|     //_stopButton->SetBitmap(wxArtProvider::GetBitmap(wxART_ERROR, | ||||
|     // wxART_BUTTON)); | ||||
|     _stopButton->Bind(wxEVT_BUTTON, | ||||
|         [this](auto&) | ||||
|         { | ||||
|             auto* event = new wxCommandEvent(PROGRESSBAR_STOP_EVENT, 0); | ||||
|             event->SetEventObject(this); | ||||
|             QueueEvent(event); | ||||
|         }); | ||||
|  | ||||
|     _rightLabel.reset(new wxStaticText(this, | ||||
|         wxID_ANY, | ||||
|         "", | ||||
|         wxDefaultPosition, | ||||
|         wxDefaultSize, | ||||
|         wxALIGN_RIGHT | wxST_NO_AUTORESIZE)); | ||||
|  | ||||
|     HideProgressBar(); | ||||
|     Layout(); | ||||
| } | ||||
|  | ||||
| void CustomStatusBar::OnSize(wxSizeEvent& event) | ||||
| { | ||||
|     auto buttonSize = _stopButton->GetEffectiveMinSize(); | ||||
|  | ||||
|     wxRect r; | ||||
|     GetFieldRect(1, r); | ||||
|     int x = r.GetLeft(); | ||||
|     int y = r.GetTop(); | ||||
|     int w = r.GetWidth(); | ||||
|     int h = r.GetHeight(); | ||||
|     constexpr int b = 5; | ||||
|  | ||||
|     _stopButton->SetPosition({x + w - buttonSize.GetWidth(), y}); | ||||
|     _stopButton->SetSize(buttonSize.GetWidth(), h); | ||||
|  | ||||
|     _progressBar->SetPosition({x, y}); | ||||
|     _progressBar->SetSize(w - buttonSize.GetWidth() - b, h); | ||||
|  | ||||
|     GetFieldRect(2, r); | ||||
|     _rightLabel->SetPosition(r.GetTopLeft()); | ||||
|     _rightLabel->SetSize(r); | ||||
| } | ||||
|  | ||||
| void CustomStatusBar::ShowProgressBar() | ||||
| { | ||||
|     _progressBar->Show(); | ||||
|     _stopButton->Show(); | ||||
| } | ||||
|  | ||||
| void CustomStatusBar::HideProgressBar() | ||||
| { | ||||
|     _progressBar->Hide(); | ||||
|     _stopButton->Hide(); | ||||
| } | ||||
|  | ||||
| void CustomStatusBar::SetProgress(int amount) | ||||
| { | ||||
|     _progressBar->SetValue(amount); | ||||
| } | ||||
|  | ||||
| void CustomStatusBar::SetLeftLabel(const std::string& text) | ||||
| { | ||||
| 	SetStatusText(text, 0); | ||||
| } | ||||
|  | ||||
| void CustomStatusBar::SetRightLabel(const std::string& text) | ||||
| { | ||||
|     _rightLabel->SetLabel(text); | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/gui/customstatusbar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/gui/customstatusbar.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| #ifndef CUSTOMSTATUSBAR_H | ||||
| #define CUSTOMSTATUSBAR_H | ||||
|  | ||||
| class wxGauge; | ||||
| class wxButton; | ||||
|  | ||||
| wxDECLARE_EVENT(PROGRESSBAR_STOP_EVENT, wxCommandEvent); | ||||
|  | ||||
| class CustomStatusBar : public wxStatusBar | ||||
| { | ||||
| public: | ||||
|     CustomStatusBar(wxWindow* parent, wxWindowID id); | ||||
|  | ||||
| public: | ||||
|     void ShowProgressBar(); | ||||
|     void HideProgressBar(); | ||||
|     void SetProgress(int amount); | ||||
| 	void SetLeftLabel(const std::string& text); | ||||
|     void SetRightLabel(const std::string& text); | ||||
|  | ||||
| private: | ||||
|     void OnSize(wxSizeEvent& event); | ||||
|  | ||||
| private: | ||||
|     std::unique_ptr<wxGauge> _progressBar; | ||||
|     std::unique_ptr<wxButton> _stopButton; | ||||
|     std::unique_ptr<wxStaticText> _rightLabel; | ||||
|  | ||||
|     DECLARE_EVENT_TABLE(); | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -1,7 +1,7 @@ | ||||
| #include "globals.h" | ||||
| #include "gui.h" | ||||
| #include "fluxviewercontrol.h" | ||||
| #include "hexviewerwindow.h" | ||||
| #include "textviewerwindow.h" | ||||
| #include "lib/flux.h" | ||||
| #include "lib/fluxmap.h" | ||||
| #include "lib/sector.h" | ||||
| @@ -389,20 +389,21 @@ void FluxViewerControl::ShowSectorMenu(std::shared_ptr<const Sector> sector) | ||||
| { | ||||
| 	wxMenu menu; | ||||
|  | ||||
| 	menu.Bind(wxEVT_COMMAND_MENU_SELECTED, | ||||
| 	menu.Bind(wxEVT_MENU, | ||||
| 		[&] (wxCommandEvent&) { | ||||
| 			DisplayDecodedData(sector); | ||||
| 		}, | ||||
| 		menu.Append(wxID_ANY, "Show decoded data")->GetId() | ||||
| 	); | ||||
|  | ||||
| 	menu.Bind(wxEVT_COMMAND_MENU_SELECTED, | ||||
| 	menu.Bind(wxEVT_MENU, | ||||
| 		[&] (wxCommandEvent&) { | ||||
| 			DisplayRawData(sector); | ||||
| 		}, | ||||
| 		menu.Append(wxID_ANY, "Show raw data")->GetId() | ||||
| 	); | ||||
|  | ||||
| 	_rightClicked = false; | ||||
| 	PopupMenu(&menu, _mouseX, _mouseY); | ||||
| } | ||||
|  | ||||
| @@ -417,6 +418,7 @@ void FluxViewerControl::ShowRecordMenu(const Location& location, std::shared_ptr | ||||
| 		menu.Append(wxID_ANY, "Show record data")->GetId() | ||||
| 	); | ||||
|  | ||||
| 	_rightClicked = false; | ||||
| 	PopupMenu(&menu, _mouseX, _mouseY); | ||||
| } | ||||
|  | ||||
| @@ -443,7 +445,7 @@ void FluxViewerControl::DisplayDecodedData(std::shared_ptr<const Sector> sector) | ||||
|  | ||||
| 	hexdump(s, sector->data); | ||||
|  | ||||
| 	HexViewerWindow::Create(this, title, s.str()); | ||||
| 	TextViewerWindow::Create(this, title, s.str())->Show(); | ||||
| } | ||||
|  | ||||
| void FluxViewerControl::DisplayRawData(std::shared_ptr<const Sector> sector) | ||||
| @@ -462,7 +464,7 @@ void FluxViewerControl::DisplayRawData(std::shared_ptr<const Sector> sector) | ||||
| 		hexdump(s, record->rawData); | ||||
| 	} | ||||
|  | ||||
| 	HexViewerWindow::Create(this, title, s.str()); | ||||
| 	TextViewerWindow::Create(this, title, s.str())->Show(); | ||||
| } | ||||
|  | ||||
| void FluxViewerControl::DisplayRawData(const Location& location, std::shared_ptr<const Record> record) | ||||
| @@ -474,5 +476,5 @@ void FluxViewerControl::DisplayRawData(const Location& location, std::shared_ptr | ||||
| 	s << title << "\n\n"; | ||||
| 	hexdump(s, record->rawData); | ||||
|  | ||||
| 	HexViewerWindow::Create(this, title, s.str()); | ||||
| 	TextViewerWindow::Create(this, title, s.str())->Show(); | ||||
| } | ||||
|   | ||||
| @@ -9,6 +9,8 @@ class MainWindow; | ||||
| extern void runOnUiThread(std::function<void()> callback); | ||||
| extern void runOnWorkerThread(std::function<void()> callback); | ||||
|  | ||||
| wxDECLARE_EVENT(UPDATE_STATE_EVENT, wxCommandEvent); | ||||
|  | ||||
| template <typename R> | ||||
| static inline R runOnUiThread(std::function<R()> callback) | ||||
| { | ||||
| @@ -36,9 +38,13 @@ public: | ||||
| protected: | ||||
| 	virtual wxThread::ExitCode Entry(); | ||||
|  | ||||
| private: | ||||
| 	static wxWindow* CreateMainWindow(); | ||||
| 	void SendUpdateEvent(); | ||||
|  | ||||
| private: | ||||
| 	std::function<void()> _callback; | ||||
| 	MainWindow* _mainWindow; | ||||
| 	wxWindow* _mainWindow; | ||||
| }; | ||||
| wxDECLARE_APP(FluxEngineApp); | ||||
|  | ||||
|   | ||||
| @@ -1,27 +0,0 @@ | ||||
| #include "globals.h" | ||||
| #include "gui.h" | ||||
| #include "layout.h" | ||||
| #include "hexviewerwindow.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| HexViewerWindow::HexViewerWindow(wxWindow* parent, | ||||
| 		const std::string& title, const std::string& text): | ||||
| 	HexViewerWindowGen(parent) | ||||
| { | ||||
| 	auto size = hexEntry->GetTextExtent("M"); | ||||
| 	SetSize(size.Scale(85, 25)); | ||||
| 	SetTitle(title); | ||||
| 	hexEntry->SetValue(text); | ||||
| } | ||||
|  | ||||
| void HexViewerWindow::Create(wxWindow* parent, const std::string& title, const std::string& text) | ||||
| { | ||||
| 	(new HexViewerWindow(parent, title, text))->Show(true); | ||||
| } | ||||
|  | ||||
| void HexViewerWindow::OnExit(wxCommandEvent& event) | ||||
| { | ||||
|     Close(true); | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1,18 +0,0 @@ | ||||
| #ifndef HEXVIEWERWINDOW_H | ||||
| #define HEXVIEWERWINDOW_H | ||||
|  | ||||
| #include "layout.h" | ||||
|  | ||||
| class HexViewerWindow : public HexViewerWindowGen | ||||
| { | ||||
| public: | ||||
|     HexViewerWindow(wxWindow* parent, const std::string& title, const std::string& text); | ||||
|  | ||||
|     static void Create(wxWindow* parent, const std::string& title, const std::string& text); | ||||
|  | ||||
| private: | ||||
|     void OnExit(wxCommandEvent& event); | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @@ -11,245 +11,393 @@ | ||||
|  | ||||
| MainWindowGen::MainWindowGen( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) | ||||
| { | ||||
| 	this->SetSizeHints( wxSize( 450,500 ), wxDefaultSize ); | ||||
| 	this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) ); | ||||
| 	this->SetSizeHints( wxDefaultSize, wxDefaultSize ); | ||||
| 	this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ); | ||||
|  | ||||
| 	bSizer1 = new wxFlexGridSizer( 0, 2, 0, 0 ); | ||||
| 	bSizer1->AddGrowableCol( 1 ); | ||||
| 	bSizer1->AddGrowableRow( 0 ); | ||||
| 	bSizer1->SetFlexibleDirection( wxHORIZONTAL ); | ||||
| 	bSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	wxFlexGridSizer* fgSizer4; | ||||
| 	fgSizer4 = new wxFlexGridSizer( 2, 1, 0, 0 ); | ||||
| 	fgSizer4->AddGrowableRow( 0 ); | ||||
| 	fgSizer4->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer4->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	visualiser = new VisualisationControl( this, wxID_ANY, wxDefaultPosition, wxSize( 200,480 ), wxBORDER_THEME ); | ||||
| 	visualiser->SetMinSize( wxSize( 200,480 ) ); | ||||
|  | ||||
| 	fgSizer4->Add( visualiser, 1, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	stopButton = new wxButton( this, wxID_ANY, wxT("Stop"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	fgSizer4->Add( stopButton, 0, wxALIGN_CENTER|wxALL, 5 ); | ||||
|  | ||||
|  | ||||
| 	bSizer1->Add( fgSizer4, 1, wxEXPAND, 5 ); | ||||
|  | ||||
| 	wxFlexGridSizer* fgSizer2; | ||||
| 	fgSizer2 = new wxFlexGridSizer( 0, 1, 0, 0 ); | ||||
| 	fgSizer2->AddGrowableCol( 0 ); | ||||
| 	fgSizer2->AddGrowableRow( 1 ); | ||||
| 	fgSizer2->SetFlexibleDirection( wxVERTICAL ); | ||||
| 	fgSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); | ||||
|  | ||||
| 	wxFlexGridSizer* fgSizer3; | ||||
| 	fgSizer3 = new wxFlexGridSizer( 0, 2, 0, 0 ); | ||||
| 	fgSizer3->AddGrowableCol( 1 ); | ||||
| 	fgSizer3->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	m_staticText4 = new wxStaticText( this, wxID_ANY, wxT("Device:"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_staticText4->Wrap( -1 ); | ||||
| 	fgSizer3->Add( m_staticText4, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxALL, 5 ); | ||||
|  | ||||
| 	deviceCombo = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_SORT ); | ||||
| 	fgSizer3->Add( deviceCombo, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	m_staticText5 = new wxStaticText( this, wxID_ANY, wxT("Flux source/sink:"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_staticText5->Wrap( -1 ); | ||||
| 	fgSizer3->Add( m_staticText5, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxALL, 5 ); | ||||
|  | ||||
| 	fluxSourceSinkCombo = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); | ||||
| 	fluxSourceSinkCombo->Append( wxT("drive:0") ); | ||||
| 	fluxSourceSinkCombo->Append( wxT("drive:1") ); | ||||
| 	fgSizer3->Add( fluxSourceSinkCombo, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	m_staticText51 = new wxStaticText( this, wxID_ANY, wxT("Format:"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_staticText51->Wrap( -1 ); | ||||
| 	fgSizer3->Add( m_staticText51, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxALL, 5 ); | ||||
|  | ||||
| 	wxArrayString formatChoiceChoices; | ||||
| 	formatChoice = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, formatChoiceChoices, wxCB_SORT ); | ||||
| 	formatChoice->SetSelection( 0 ); | ||||
| 	fgSizer3->Add( formatChoice, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	fgSizer3->Add( 0, 0, 1, wxEXPAND, 5 ); | ||||
|  | ||||
| 	highDensityToggle = new wxCheckBox( this, wxID_ANY, wxT("High density disk"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	fgSizer3->Add( highDensityToggle, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_LEFT|wxALL, 5 ); | ||||
|  | ||||
|  | ||||
| 	fgSizer2->Add( fgSizer3, 1, wxEXPAND, 5 ); | ||||
|  | ||||
| 	notebook = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_panel1 = new wxPanel( notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxFlexGridSizer* fgSizer5; | ||||
| 	fgSizer5 = new wxFlexGridSizer( 0, 2, 0, 0 ); | ||||
| 	fgSizer5->AddGrowableCol( 0 ); | ||||
| 	fgSizer5->AddGrowableRow( 0 ); | ||||
| 	fgSizer5->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	additionalSettingsEntry = new wxTextCtrl( m_panel1, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE ); | ||||
| 	fgSizer5->Add( additionalSettingsEntry, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	m_panel1->SetSizer( fgSizer5 ); | ||||
| 	m_panel1->Layout(); | ||||
| 	fgSizer5->Fit( m_panel1 ); | ||||
| 	notebook->AddPage( m_panel1, wxT("Additional settings"), true ); | ||||
| 	m_panel2 = new wxPanel( notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxFlexGridSizer* fgSizer8; | ||||
| 	fgSizer8 = new wxFlexGridSizer( 0, 2, 0, 0 ); | ||||
| 	fgSizer8->AddGrowableCol( 0 ); | ||||
| 	fgSizer8->AddGrowableRow( 0 ); | ||||
| 	fgSizer8->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	logEntry = new wxTextCtrl( m_panel2, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH ); | ||||
| 	fgSizer8->Add( logEntry, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	m_panel2->SetSizer( fgSizer8 ); | ||||
| 	m_panel2->Layout(); | ||||
| 	fgSizer8->Fit( m_panel2 ); | ||||
| 	notebook->AddPage( m_panel2, wxT("Logs"), false ); | ||||
| 	m_panel3 = new wxPanel( notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxFlexGridSizer* fgSizer9; | ||||
| 	fgSizer9 = new wxFlexGridSizer( 0, 2, 0, 0 ); | ||||
| 	fgSizer9->AddGrowableCol( 0 ); | ||||
| 	fgSizer9->AddGrowableRow( 0 ); | ||||
| 	fgSizer9->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer9->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	protoConfigEntry = new wxTextCtrl( m_panel3, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY ); | ||||
| 	fgSizer9->Add( protoConfigEntry, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	m_panel3->SetSizer( fgSizer9 ); | ||||
| 	m_panel3->Layout(); | ||||
| 	fgSizer9->Fit( m_panel3 ); | ||||
| 	notebook->AddPage( m_panel3, wxT("Debug info"), false ); | ||||
|  | ||||
| 	fgSizer2->Add( notebook, 1, wxEXPAND | wxALL, 5 ); | ||||
|  | ||||
| 	wxGridSizer* m_sizer; | ||||
| 	m_sizer = new wxGridSizer( 0, 2, 0, 0 ); | ||||
|  | ||||
| 	readFluxButton = new wxButton( this, wxID_ANY, wxT("Read flux"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_sizer->Add( readFluxButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	readImageButton = new wxButton( this, wxID_ANY, wxT("Read image"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_sizer->Add( readImageButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	writeFluxButton = new wxButton( this, wxID_ANY, wxT("Write flux"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_sizer->Add( writeFluxButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	writeImageButton = new wxButton( this, wxID_ANY, wxT("Write image"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_sizer->Add( writeImageButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	fgSizer2->Add( m_sizer, 1, wxEXPAND|wxFIXED_MINSIZE, 5 ); | ||||
|  | ||||
|  | ||||
| 	bSizer1->Add( fgSizer2, 1, wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	this->SetSizer( bSizer1 ); | ||||
| 	this->Layout(); | ||||
| 	m_menubar1 = new wxMenuBar( 0 ); | ||||
| 	menuBar = new wxMenuBar( 0 ); | ||||
| 	m_menu1 = new wxMenu(); | ||||
| 	wxMenuItem* m_menuItem2; | ||||
| 	m_menuItem2 = new wxMenuItem( m_menu1, wxID_ABOUT, wxString( wxT("About") ) , wxEmptyString, wxITEM_NORMAL ); | ||||
| 	m_menuItem2 = new wxMenuItem( m_menu1, wxID_ABOUT, wxString( wxT("&About") ) , wxEmptyString, wxITEM_NORMAL ); | ||||
| 	m_menu1->Append( m_menuItem2 ); | ||||
|  | ||||
| 	wxMenuItem* m_menuItem1; | ||||
| 	m_menuItem1 = new wxMenuItem( m_menu1, wxID_EXIT, wxString( wxT("E&xit") ) , wxEmptyString, wxITEM_NORMAL ); | ||||
| 	m_menu1->Append( m_menuItem1 ); | ||||
|  | ||||
| 	m_menubar1->Append( m_menu1, wxT("&File") ); | ||||
| 	menuBar->Append( m_menu1, wxT("&File") ); | ||||
|  | ||||
| 	this->SetMenuBar( m_menubar1 ); | ||||
| 	m_menu2 = new wxMenu(); | ||||
| 	wxMenuItem* m_menuItem3; | ||||
| 	m_menuItem3 = new wxMenuItem( m_menu2, wxID_ANY, wxString( wxT("Show &logs...") ) + wxT('\t') + wxT("CTRL+L"), wxEmptyString, wxITEM_NORMAL ); | ||||
| 	m_menu2->Append( m_menuItem3 ); | ||||
|  | ||||
| 	wxMenuItem* m_menuItem4; | ||||
| 	m_menuItem4 = new wxMenuItem( m_menu2, wxID_ANY, wxString( wxT("Show current &configuration...") ) , wxEmptyString, wxITEM_NORMAL ); | ||||
| 	m_menu2->Append( m_menuItem4 ); | ||||
|  | ||||
| 	menuBar->Append( m_menu2, wxT("&View") ); | ||||
|  | ||||
| 	this->SetMenuBar( menuBar ); | ||||
|  | ||||
| 	wxBoxSizer* bSizer4; | ||||
| 	bSizer4 = new wxBoxSizer( wxVERTICAL ); | ||||
|  | ||||
| 	dataNotebook = new wxSimplebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	idlePanel = new wxScrolledWindow( dataNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTAB_TRAVERSAL|wxVSCROLL ); | ||||
| 	idlePanel->SetScrollRate( 5, 5 ); | ||||
| 	wxGridSizer* gSizer11; | ||||
| 	gSizer11 = new wxGridSizer( 1, 1, 0, 0 ); | ||||
|  | ||||
| 	wxFlexGridSizer* fgSizer8; | ||||
| 	fgSizer8 = new wxFlexGridSizer( 0, 1, 0, 0 ); | ||||
| 	fgSizer8->AddGrowableCol( 0 ); | ||||
| 	fgSizer8->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); | ||||
|  | ||||
| 	fgSizer8->SetMinSize( wxSize( 400,-1 ) ); | ||||
| 	m_staticText61 = new wxStaticText( idlePanel, wxID_ANY, wxT("Pick one of:"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_staticText61->Wrap( -1 ); | ||||
| 	fgSizer8->Add( m_staticText61, 0, wxALIGN_CENTER|wxALL, 5 ); | ||||
|  | ||||
| 	realDiskRadioButton = new wxRadioButton( idlePanel, wxID_ANY, wxT("Real disk"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP ); | ||||
| 	realDiskRadioButton->SetToolTip( wxT("You want to use a real floppy drive attached to real hardware.") ); | ||||
|  | ||||
| 	fgSizer8->Add( realDiskRadioButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	realDiskRadioButtonPanel = new wxPanel( idlePanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxBoxSizer* bSizer3; | ||||
| 	bSizer3 = new wxBoxSizer( wxVERTICAL ); | ||||
|  | ||||
| 	deviceCombo = new wxComboBox( realDiskRadioButtonPanel, wxID_ANY, wxT("Combo!"), wxDefaultPosition, wxDefaultSize, 0, NULL, 0 ); | ||||
| 	deviceCombo->SetToolTip( wxT("Device ID to use (either the path of a serial port or a USB serial number).") ); | ||||
|  | ||||
| 	bSizer3->Add( deviceCombo, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	wxString driveChoiceChoices[] = { wxT("drive:0"), wxT("drive:1") }; | ||||
| 	int driveChoiceNChoices = sizeof( driveChoiceChoices ) / sizeof( wxString ); | ||||
| 	driveChoice = new wxChoice( realDiskRadioButtonPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, driveChoiceNChoices, driveChoiceChoices, 0 ); | ||||
| 	driveChoice->SetSelection( 0 ); | ||||
| 	driveChoice->SetToolTip( wxT("Which drive on the device to use.") ); | ||||
|  | ||||
| 	bSizer3->Add( driveChoice, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	highDensityToggle = new wxCheckBox( realDiskRadioButtonPanel, wxID_ANY, wxT("This is a high density disk"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	highDensityToggle->SetToolTip( wxT("If you are using a high density disk, select this.\nThis can be detected automatically for 3.5\"\ndisks but needs to be set manually for everything\nelse.") ); | ||||
|  | ||||
| 	bSizer3->Add( highDensityToggle, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	// Connect Events | ||||
| 	m_menu1->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainWindowGen::OnAbout ), this, m_menuItem2->GetId()); | ||||
| 	m_menu1->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainWindowGen::OnExit ), this, m_menuItem1->GetId()); | ||||
| } | ||||
| 	realDiskRadioButtonPanel->SetSizer( bSizer3 ); | ||||
| 	realDiskRadioButtonPanel->Layout(); | ||||
| 	bSizer3->Fit( realDiskRadioButtonPanel ); | ||||
| 	fgSizer8->Add( realDiskRadioButtonPanel, 1, wxEXPAND | wxALL, 5 ); | ||||
|  | ||||
| MainWindowGen::~MainWindowGen() | ||||
| { | ||||
| 	// Disconnect Events | ||||
| 	fluxImageRadioButton = new wxRadioButton( idlePanel, wxID_ANY, wxT("Flux image"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	fluxImageRadioButton->SetToolTip( wxT("You want to use an unencoded flux file.") ); | ||||
|  | ||||
| } | ||||
| 	fgSizer8->Add( fluxImageRadioButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| FluxViewerWindowGen::FluxViewerWindowGen( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) | ||||
| { | ||||
| 	this->SetSizeHints( wxDefaultSize, wxDefaultSize ); | ||||
| 	fluxImageRadioButtonPanel = new wxPanel( idlePanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxGridSizer* gSizer121; | ||||
| 	gSizer121 = new wxGridSizer( 1, 1, 0, 0 ); | ||||
|  | ||||
| 	m_menubar2 = new wxMenuBar( 0 ); | ||||
| 	m_menu1 = new wxMenu(); | ||||
| 	wxMenuItem* m_menuItem1; | ||||
| 	m_menuItem1 = new wxMenuItem( m_menu1, wxID_CLOSE, wxString( wxT("&Close") ) , wxEmptyString, wxITEM_NORMAL ); | ||||
| 	m_menu1->Append( m_menuItem1 ); | ||||
| 	fluxImagePicker = new wxFilePickerCtrl( fluxImageRadioButtonPanel, wxID_ANY, wxEmptyString, wxT("Select a file"), wxT("*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL ); | ||||
| 	fluxImagePicker->SetToolTip( wxT("Path to a .flux, .scp or other flux file.") ); | ||||
|  | ||||
| 	m_menubar2->Append( m_menu1, wxT("&Window") ); | ||||
|  | ||||
| 	this->SetMenuBar( m_menubar2 ); | ||||
|  | ||||
| 	wxBoxSizer* bSizer1; | ||||
| 	bSizer1 = new wxBoxSizer( wxVERTICAL ); | ||||
|  | ||||
| 	fluxviewer = new FluxViewerControl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	bSizer1->Add( fluxviewer, 1, wxEXPAND, 5 ); | ||||
|  | ||||
| 	scrollbar = new wxScrollBar( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL ); | ||||
| 	bSizer1->Add( scrollbar, 0, wxALIGN_BOTTOM|wxEXPAND, 5 ); | ||||
| 	gSizer121->Add( fluxImagePicker, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	this->SetSizer( bSizer1 ); | ||||
| 	fluxImageRadioButtonPanel->SetSizer( gSizer121 ); | ||||
| 	fluxImageRadioButtonPanel->Layout(); | ||||
| 	gSizer121->Fit( fluxImageRadioButtonPanel ); | ||||
| 	fgSizer8->Add( fluxImageRadioButtonPanel, 1, wxEXPAND | wxALL, 5 ); | ||||
|  | ||||
| 	diskImageRadioButton = new wxRadioButton( idlePanel, wxID_ANY, wxT("Disk image"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	diskImageRadioButton->SetToolTip( wxT("You want to use a decode file system disk image.") ); | ||||
|  | ||||
| 	fgSizer8->Add( diskImageRadioButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	diskImageRadioButtonPanel = new wxPanel( idlePanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxGridSizer* gSizer1211; | ||||
| 	gSizer1211 = new wxGridSizer( 1, 1, 0, 0 ); | ||||
|  | ||||
| 	diskImagePicker = new wxFilePickerCtrl( diskImageRadioButtonPanel, wxID_ANY, wxEmptyString, wxT("Select a file"), wxT("*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_FILE_MUST_EXIST|wxFLP_OPEN|wxFLP_USE_TEXTCTRL ); | ||||
| 	diskImagePicker->SetToolTip( wxT("The path to the disk image.") ); | ||||
|  | ||||
| 	gSizer1211->Add( diskImagePicker, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	diskImageRadioButtonPanel->SetSizer( gSizer1211 ); | ||||
| 	diskImageRadioButtonPanel->Layout(); | ||||
| 	gSizer1211->Fit( diskImageRadioButtonPanel ); | ||||
| 	fgSizer8->Add( diskImageRadioButtonPanel, 1, wxEXPAND | wxALL, 5 ); | ||||
|  | ||||
| 	m_staticText23 = new wxStaticText( idlePanel, wxID_ANY, wxT("then select a format:"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_staticText23->Wrap( -1 ); | ||||
| 	fgSizer8->Add( m_staticText23, 0, wxALIGN_CENTER|wxALL, 5 ); | ||||
|  | ||||
| 	m_panel11 = new wxPanel( idlePanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxFlexGridSizer* fgSizer6; | ||||
| 	fgSizer6 = new wxFlexGridSizer( 1, 2, 0, 0 ); | ||||
| 	fgSizer6->AddGrowableCol( 0 ); | ||||
| 	fgSizer6->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer6->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	wxArrayString formatChoiceChoices; | ||||
| 	formatChoice = new wxChoice( m_panel11, wxID_ANY, wxDefaultPosition, wxDefaultSize, formatChoiceChoices, 0 ); | ||||
| 	formatChoice->SetSelection( 0 ); | ||||
| 	formatChoice->SetToolTip( wxT("The format of the disk.") ); | ||||
|  | ||||
| 	fgSizer6->Add( formatChoice, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	customConfigurationButton = new wxButton( m_panel11, wxID_ANY, wxT("Customise..."), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	customConfigurationButton->SetToolTip( wxT("Allows you to enter arbitrary configuration parameters.") ); | ||||
|  | ||||
| 	fgSizer6->Add( customConfigurationButton, 0, wxALL, 5 ); | ||||
|  | ||||
|  | ||||
| 	m_panel11->SetSizer( fgSizer6 ); | ||||
| 	m_panel11->Layout(); | ||||
| 	fgSizer6->Fit( m_panel11 ); | ||||
| 	fgSizer8->Add( m_panel11, 1, wxEXPAND | wxALL, 5 ); | ||||
|  | ||||
| 	m_staticText19 = new wxStaticText( idlePanel, wxID_ANY, wxT("and press one of:"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_staticText19->Wrap( -1 ); | ||||
| 	fgSizer8->Add( m_staticText19, 0, wxALIGN_CENTER|wxALL, 5 ); | ||||
|  | ||||
| 	wxGridSizer* gSizer9; | ||||
| 	gSizer9 = new wxGridSizer( 1, 0, 0, 0 ); | ||||
|  | ||||
| 	readButton = new wxButton( idlePanel, wxID_ANY, wxT("Read disk"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	readButton->SetLabelMarkup( wxT("Read disk") ); | ||||
| 	readButton->SetBitmap( wxArtProvider::GetBitmap( wxART_FILE_OPEN, wxART_TOOLBAR ) ); | ||||
| 	readButton->SetToolTip( wxT("Read and decode, producing a disk image from a real disk or flux file.") ); | ||||
|  | ||||
| 	gSizer9->Add( readButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	writeButton = new wxButton( idlePanel, wxID_ANY, wxT("Write disk"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
|  | ||||
| 	writeButton->SetBitmap( wxArtProvider::GetBitmap( wxART_FILE_SAVE, wxART_TOOLBAR ) ); | ||||
| 	writeButton->SetBitmapDisabled( wxNullBitmap ); | ||||
| 	writeButton->SetToolTip( wxT("Encode and write to either a real disk or a flux file.") ); | ||||
|  | ||||
| 	gSizer9->Add( writeButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	browseButton = new wxButton( idlePanel, wxID_ANY, wxT("Browse disk"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
|  | ||||
| 	browseButton->SetBitmap( wxArtProvider::GetBitmap( wxART_FOLDER_OPEN, wxART_TOOLBAR ) ); | ||||
| 	browseButton->Enable( false ); | ||||
| 	browseButton->SetToolTip( wxT("Access the files on the disk directly without needing to image it.") ); | ||||
|  | ||||
| 	gSizer9->Add( browseButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	fgSizer8->Add( gSizer9, 1, wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	gSizer11->Add( fgSizer8, 1, wxALIGN_CENTER|wxALL, 5 ); | ||||
|  | ||||
|  | ||||
| 	idlePanel->SetSizer( gSizer11 ); | ||||
| 	idlePanel->Layout(); | ||||
| 	gSizer11->Fit( idlePanel ); | ||||
| 	dataNotebook->AddPage( idlePanel, wxT("a page"), false ); | ||||
| 	imagePanel = new wxPanel( dataNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxBoxSizer* bSizer41; | ||||
| 	bSizer41 = new wxBoxSizer( wxVERTICAL ); | ||||
|  | ||||
| 	imagerToolbar = new wxToolBar( imagePanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_FLAT|wxTB_HORIZONTAL|wxTB_TEXT ); | ||||
| 	imagerBackTool = imagerToolbar->AddTool( wxID_ANY, wxT("Back"), wxArtProvider::GetBitmap( wxART_GO_BACK, wxART_TOOLBAR ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString, NULL ); | ||||
|  | ||||
| 	imagerToolbar->Realize(); | ||||
|  | ||||
| 	bSizer41->Add( imagerToolbar, 0, wxEXPAND, 5 ); | ||||
|  | ||||
| 	wxGridSizer* gSizer122; | ||||
| 	gSizer122 = new wxGridSizer( 0, 2, 0, 0 ); | ||||
|  | ||||
| 	wxGridSizer* gSizer5; | ||||
| 	gSizer5 = new wxGridSizer( 0, 1, 0, 0 ); | ||||
|  | ||||
| 	visualiser = new VisualisationControl( imagePanel, wxID_ANY, wxDefaultPosition, wxSize( -1,-1 ), wxBORDER_THEME ); | ||||
| 	gSizer5->Add( visualiser, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	gSizer122->Add( gSizer5, 1, wxEXPAND, 5 ); | ||||
|  | ||||
| 	wxGridSizer* gSizer7; | ||||
| 	gSizer7 = new wxGridSizer( 1, 1, 0, 0 ); | ||||
|  | ||||
| 	wxGridSizer* gSizer8; | ||||
| 	gSizer8 = new wxGridSizer( 0, 1, 0, 0 ); | ||||
|  | ||||
| 	imagerSaveImageButton = new wxButton( imagePanel, wxID_ANY, wxT("Save decoded image"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
|  | ||||
| 	imagerSaveImageButton->SetBitmap( wxArtProvider::GetBitmap( wxART_FILE_SAVE, wxART_BUTTON ) ); | ||||
| 	gSizer8->Add( imagerSaveImageButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	imagerSaveFluxButton = new wxButton( imagePanel, wxID_ANY, wxT("Save raw flux"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
|  | ||||
| 	imagerSaveFluxButton->SetBitmap( wxArtProvider::GetBitmap( wxART_FILE_SAVE_AS, wxART_BUTTON ) ); | ||||
| 	gSizer8->Add( imagerSaveFluxButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	m_staticText4 = new wxStaticText( imagePanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	m_staticText4->Wrap( -1 ); | ||||
| 	gSizer8->Add( m_staticText4, 0, wxALL, 5 ); | ||||
|  | ||||
| 	imagerGoAgainButton = new wxButton( imagePanel, wxID_ANY, wxT("Go again"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
|  | ||||
| 	imagerGoAgainButton->SetBitmap( wxArtProvider::GetBitmap( wxART_REDO, wxART_BUTTON ) ); | ||||
| 	gSizer8->Add( imagerGoAgainButton, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	gSizer7->Add( gSizer8, 1, wxALIGN_CENTER, 5 ); | ||||
|  | ||||
|  | ||||
| 	gSizer122->Add( gSizer7, 1, wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	bSizer41->Add( gSizer122, 1, wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	imagePanel->SetSizer( bSizer41 ); | ||||
| 	imagePanel->Layout(); | ||||
| 	bSizer41->Fit( imagePanel ); | ||||
| 	dataNotebook->AddPage( imagePanel, wxT("a page"), false ); | ||||
| 	browsePanel = new wxPanel( dataNotebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); | ||||
| 	wxFlexGridSizer* fgSizer23; | ||||
| 	fgSizer23 = new wxFlexGridSizer( 0, 1, 0, 0 ); | ||||
| 	fgSizer23->AddGrowableCol( 0 ); | ||||
| 	fgSizer23->AddGrowableRow( 1 ); | ||||
| 	fgSizer23->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer23->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	browserToolbar = new wxToolBar( browsePanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_FLAT|wxTB_HORIZONTAL|wxTB_TEXT ); | ||||
| 	browserBackTool = browserToolbar->AddTool( wxID_ANY, wxT("Back"), wxArtProvider::GetBitmap( wxART_GO_BACK, wxART_TOOLBAR ), wxNullBitmap, wxITEM_NORMAL, wxEmptyString, wxEmptyString, NULL ); | ||||
|  | ||||
| 	browserToolbar->Realize(); | ||||
|  | ||||
| 	fgSizer23->Add( browserToolbar, 0, wxEXPAND, 5 ); | ||||
|  | ||||
| 	m_scrolledWindow1 = new wxScrolledWindow( browsePanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxVSCROLL ); | ||||
| 	m_scrolledWindow1->SetScrollRate( 5, 5 ); | ||||
| 	wxGridSizer* gSizer13; | ||||
| 	gSizer13 = new wxGridSizer( 1, 1, 0, 0 ); | ||||
|  | ||||
| 	browserView = new wxDataViewCtrl( m_scrolledWindow1, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	browserFilenameColumn = browserView->AppendTextColumn( wxT("Filename"), 0, wxDATAVIEW_CELL_INERT, -1, static_cast<wxAlignment>(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); | ||||
| 	browserModeColumn = browserView->AppendTextColumn( wxT("Mode"), 1, wxDATAVIEW_CELL_INERT, -1, static_cast<wxAlignment>(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); | ||||
| 	browserLengthColumn = browserView->AppendTextColumn( wxT("Length"), 2, wxDATAVIEW_CELL_INERT, -1, static_cast<wxAlignment>(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); | ||||
| 	browserExtraColumn = browserView->AppendTextColumn( wxT("Additional properties"), 0, wxDATAVIEW_CELL_INERT, -1, static_cast<wxAlignment>(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE ); | ||||
| 	gSizer13->Add( browserView, 0, wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	m_scrolledWindow1->SetSizer( gSizer13 ); | ||||
| 	m_scrolledWindow1->Layout(); | ||||
| 	gSizer13->Fit( m_scrolledWindow1 ); | ||||
| 	fgSizer23->Add( m_scrolledWindow1, 1, wxEXPAND | wxALL, 5 ); | ||||
|  | ||||
| 	wxGridSizer* gSizer12; | ||||
| 	gSizer12 = new wxGridSizer( 0, 2, 0, 0 ); | ||||
|  | ||||
| 	browserDiscardButton = new wxButton( browsePanel, wxID_ANY, wxT("Discard pending changes"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
|  | ||||
| 	browserDiscardButton->SetBitmap( wxArtProvider::GetBitmap( wxART_WARNING, wxART_BUTTON ) ); | ||||
| 	gSizer12->Add( browserDiscardButton, 0, wxALIGN_CENTER|wxALL, 5 ); | ||||
|  | ||||
| 	browserCommitButton = new wxButton( browsePanel, wxID_ANY, wxT("Commit pending changes to disk"), wxDefaultPosition, wxDefaultSize, 0 ); | ||||
|  | ||||
| 	browserCommitButton->SetBitmap( wxArtProvider::GetBitmap( wxART_FILE_SAVE, wxART_BUTTON ) ); | ||||
| 	gSizer12->Add( browserCommitButton, 0, wxALIGN_CENTER|wxALL, 5 ); | ||||
|  | ||||
|  | ||||
| 	fgSizer23->Add( gSizer12, 1, wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	browsePanel->SetSizer( fgSizer23 ); | ||||
| 	browsePanel->Layout(); | ||||
| 	fgSizer23->Fit( browsePanel ); | ||||
| 	dataNotebook->AddPage( browsePanel, wxT("a page"), false ); | ||||
|  | ||||
| 	bSizer4->Add( dataNotebook, 1, wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	this->SetSizer( bSizer4 ); | ||||
| 	this->Layout(); | ||||
|  | ||||
| 	this->Centre( wxBOTH ); | ||||
|  | ||||
| 	// Connect Events | ||||
| 	m_menu1->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( FluxViewerWindowGen::OnExit ), this, m_menuItem1->GetId()); | ||||
| 	this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainWindowGen::OnClose ) ); | ||||
| 	m_menu1->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainWindowGen::OnAboutMenuItem ), this, m_menuItem2->GetId()); | ||||
| 	m_menu1->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainWindowGen::OnExit ), this, m_menuItem1->GetId()); | ||||
| 	m_menu2->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainWindowGen::OnShowLogWindow ), this, m_menuItem3->GetId()); | ||||
| 	m_menu2->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainWindowGen::OnShowConfigWindow ), this, m_menuItem4->GetId()); | ||||
| 	realDiskRadioButton->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainWindowGen::OnConfigRadioButtonClicked ), NULL, this ); | ||||
| 	deviceCombo->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	driveChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	highDensityToggle->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	fluxImageRadioButton->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainWindowGen::OnConfigRadioButtonClicked ), NULL, this ); | ||||
| 	fluxImagePicker->Connect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	diskImageRadioButton->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainWindowGen::OnConfigRadioButtonClicked ), NULL, this ); | ||||
| 	diskImagePicker->Connect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	formatChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	customConfigurationButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnCustomConfigurationButton ), NULL, this ); | ||||
| 	readButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnReadButton ), NULL, this ); | ||||
| 	writeButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnWriteButton ), NULL, this ); | ||||
| 	this->Connect( imagerBackTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBackButton ) ); | ||||
| 	imagerSaveImageButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnSaveImageButton ), NULL, this ); | ||||
| 	imagerSaveFluxButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnSaveFluxButton ), NULL, this ); | ||||
| 	imagerGoAgainButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnImagerGoAgainButton ), NULL, this ); | ||||
| 	this->Connect( browserBackTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBackButton ) ); | ||||
| } | ||||
|  | ||||
| FluxViewerWindowGen::~FluxViewerWindowGen() | ||||
| MainWindowGen::~MainWindowGen() | ||||
| { | ||||
| 	// Disconnect Events | ||||
| 	this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainWindowGen::OnClose ) ); | ||||
| 	realDiskRadioButton->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainWindowGen::OnConfigRadioButtonClicked ), NULL, this ); | ||||
| 	deviceCombo->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	driveChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	highDensityToggle->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	fluxImageRadioButton->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainWindowGen::OnConfigRadioButtonClicked ), NULL, this ); | ||||
| 	fluxImagePicker->Disconnect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	diskImageRadioButton->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( MainWindowGen::OnConfigRadioButtonClicked ), NULL, this ); | ||||
| 	diskImagePicker->Disconnect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	formatChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( MainWindowGen::OnControlsChanged ), NULL, this ); | ||||
| 	customConfigurationButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnCustomConfigurationButton ), NULL, this ); | ||||
| 	readButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnReadButton ), NULL, this ); | ||||
| 	writeButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnWriteButton ), NULL, this ); | ||||
| 	this->Disconnect( imagerBackTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBackButton ) ); | ||||
| 	imagerSaveImageButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnSaveImageButton ), NULL, this ); | ||||
| 	imagerSaveFluxButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnSaveFluxButton ), NULL, this ); | ||||
| 	imagerGoAgainButton->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainWindowGen::OnImagerGoAgainButton ), NULL, this ); | ||||
| 	this->Disconnect( browserBackTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBackButton ) ); | ||||
|  | ||||
| } | ||||
|  | ||||
| HexViewerWindowGen::HexViewerWindowGen( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) | ||||
| TextViewerWindowGen::TextViewerWindowGen( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) | ||||
| { | ||||
| 	this->SetSizeHints( wxDefaultSize, wxDefaultSize ); | ||||
|  | ||||
| 	m_menubar2 = new wxMenuBar( 0 ); | ||||
| 	m_menu1 = new wxMenu(); | ||||
| 	wxMenuItem* m_menuItem1; | ||||
| 	m_menuItem1 = new wxMenuItem( m_menu1, wxID_CLOSE, wxString( wxT("&Close") ) , wxEmptyString, wxITEM_NORMAL ); | ||||
| 	m_menu1->Append( m_menuItem1 ); | ||||
|  | ||||
| 	m_menubar2->Append( m_menu1, wxT("&Window") ); | ||||
|  | ||||
| 	this->SetMenuBar( m_menubar2 ); | ||||
|  | ||||
| 	wxFlexGridSizer* fgSizer8; | ||||
| 	fgSizer8 = new wxFlexGridSizer( 1, 1, 0, 0 ); | ||||
| 	fgSizer8 = new wxFlexGridSizer( 0, 1, 0, 0 ); | ||||
| 	fgSizer8->AddGrowableCol( 0 ); | ||||
| 	fgSizer8->AddGrowableRow( 0 ); | ||||
| 	fgSizer8->SetFlexibleDirection( wxHORIZONTAL ); | ||||
| 	fgSizer8->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); | ||||
|  | ||||
| 	hexEntry = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH ); | ||||
| 	hexEntry->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); | ||||
| 	textControl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH ); | ||||
| 	textControl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); | ||||
|  | ||||
| 	fgSizer8->Add( hexEntry, 0, wxALL|wxEXPAND, 5 ); | ||||
| 	fgSizer8->Add( textControl, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	m_sdbSizer2 = new wxStdDialogButtonSizer(); | ||||
| 	m_sdbSizer2OK = new wxButton( this, wxID_OK ); | ||||
| 	m_sdbSizer2->AddButton( m_sdbSizer2OK ); | ||||
| 	m_sdbSizer2->Realize(); | ||||
|  | ||||
| 	fgSizer8->Add( m_sdbSizer2, 1, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	this->SetSizer( fgSizer8 ); | ||||
| @@ -258,11 +406,104 @@ HexViewerWindowGen::HexViewerWindowGen( wxWindow* parent, wxWindowID id, const w | ||||
| 	this->Centre( wxBOTH ); | ||||
|  | ||||
| 	// Connect Events | ||||
| 	m_menu1->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( HexViewerWindowGen::OnExit ), this, m_menuItem1->GetId()); | ||||
| 	this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( TextViewerWindowGen::OnClose ) ); | ||||
| 	m_sdbSizer2OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TextViewerWindowGen::OnClose ), NULL, this ); | ||||
| } | ||||
|  | ||||
| HexViewerWindowGen::~HexViewerWindowGen() | ||||
| TextViewerWindowGen::~TextViewerWindowGen() | ||||
| { | ||||
| 	// Disconnect Events | ||||
| 	this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( TextViewerWindowGen::OnClose ) ); | ||||
| 	m_sdbSizer2OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TextViewerWindowGen::OnClose ), NULL, this ); | ||||
|  | ||||
| } | ||||
|  | ||||
| FluxViewerWindowGen::FluxViewerWindowGen( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) | ||||
| { | ||||
| 	this->SetSizeHints( wxSize( 200,100 ), wxDefaultSize ); | ||||
|  | ||||
| 	wxFlexGridSizer* fgSizer5; | ||||
| 	fgSizer5 = new wxFlexGridSizer( 0, 1, 0, 0 ); | ||||
| 	fgSizer5->AddGrowableCol( 0 ); | ||||
| 	fgSizer5->AddGrowableRow( 0 ); | ||||
| 	fgSizer5->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer5->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); | ||||
|  | ||||
| 	fluxviewer = new FluxViewerControl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 ); | ||||
| 	fgSizer5->Add( fluxviewer, 1, wxEXPAND, 5 ); | ||||
|  | ||||
| 	scrollbar = new wxScrollBar( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSB_HORIZONTAL ); | ||||
| 	fgSizer5->Add( scrollbar, 0, wxALIGN_BOTTOM|wxEXPAND, 5 ); | ||||
|  | ||||
| 	m_sdbSizer2 = new wxStdDialogButtonSizer(); | ||||
| 	m_sdbSizer2OK = new wxButton( this, wxID_OK ); | ||||
| 	m_sdbSizer2->AddButton( m_sdbSizer2OK ); | ||||
| 	m_sdbSizer2->Realize(); | ||||
|  | ||||
| 	fgSizer5->Add( m_sdbSizer2, 1, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	this->SetSizer( fgSizer5 ); | ||||
| 	this->Layout(); | ||||
|  | ||||
| 	this->Centre( wxBOTH ); | ||||
|  | ||||
| 	// Connect Events | ||||
| 	this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FluxViewerWindowGen::OnClose ) ); | ||||
| 	m_sdbSizer2OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FluxViewerWindowGen::OnClose ), NULL, this ); | ||||
| } | ||||
|  | ||||
| FluxViewerWindowGen::~FluxViewerWindowGen() | ||||
| { | ||||
| 	// Disconnect Events | ||||
| 	this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( FluxViewerWindowGen::OnClose ) ); | ||||
| 	m_sdbSizer2OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FluxViewerWindowGen::OnClose ), NULL, this ); | ||||
|  | ||||
| } | ||||
|  | ||||
| TextEditorWindowGen::TextEditorWindowGen( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style ) | ||||
| { | ||||
| 	this->SetSizeHints( wxDefaultSize, wxDefaultSize ); | ||||
|  | ||||
| 	wxFlexGridSizer* fgSizer8; | ||||
| 	fgSizer8 = new wxFlexGridSizer( 0, 1, 0, 0 ); | ||||
| 	fgSizer8->AddGrowableCol( 0 ); | ||||
| 	fgSizer8->AddGrowableRow( 0 ); | ||||
| 	fgSizer8->SetFlexibleDirection( wxBOTH ); | ||||
| 	fgSizer8->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_ALL ); | ||||
|  | ||||
| 	textControl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_PROCESS_TAB ); | ||||
| 	textControl->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, wxEmptyString ) ); | ||||
|  | ||||
| 	fgSizer8->Add( textControl, 0, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
| 	m_sdbSizer2 = new wxStdDialogButtonSizer(); | ||||
| 	m_sdbSizer2Save = new wxButton( this, wxID_SAVE ); | ||||
| 	m_sdbSizer2->AddButton( m_sdbSizer2Save ); | ||||
| 	m_sdbSizer2Cancel = new wxButton( this, wxID_CANCEL ); | ||||
| 	m_sdbSizer2->AddButton( m_sdbSizer2Cancel ); | ||||
| 	m_sdbSizer2->Realize(); | ||||
|  | ||||
| 	fgSizer8->Add( m_sdbSizer2, 1, wxALL|wxEXPAND, 5 ); | ||||
|  | ||||
|  | ||||
| 	this->SetSizer( fgSizer8 ); | ||||
| 	this->Layout(); | ||||
| 	fgSizer8->Fit( this ); | ||||
|  | ||||
| 	this->Centre( wxBOTH ); | ||||
|  | ||||
| 	// Connect Events | ||||
| 	this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( TextEditorWindowGen::OnClose ) ); | ||||
| 	m_sdbSizer2Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TextEditorWindowGen::OnCancel ), NULL, this ); | ||||
| 	m_sdbSizer2Save->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TextEditorWindowGen::OnSave ), NULL, this ); | ||||
| } | ||||
|  | ||||
| TextEditorWindowGen::~TextEditorWindowGen() | ||||
| { | ||||
| 	// Disconnect Events | ||||
| 	this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( TextEditorWindowGen::OnClose ) ); | ||||
| 	m_sdbSizer2Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TextEditorWindowGen::OnCancel ), NULL, this ); | ||||
| 	m_sdbSizer2Save->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( TextEditorWindowGen::OnSave ), NULL, this ); | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										4233
									
								
								src/gui/layout.fbp
									
									
									
									
									
								
							
							
						
						
									
										4233
									
								
								src/gui/layout.fbp
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										169
									
								
								src/gui/layout.h
									
									
									
									
									
								
							
							
						
						
									
										169
									
								
								src/gui/layout.h
									
									
									
									
									
								
							| @@ -9,26 +9,32 @@ | ||||
|  | ||||
| #include <wx/artprov.h> | ||||
| #include <wx/xrc/xmlres.h> | ||||
| #include "visualisationcontrol.h" | ||||
| #include <wx/string.h> | ||||
| #include <wx/bitmap.h> | ||||
| #include <wx/image.h> | ||||
| #include <wx/icon.h> | ||||
| #include <wx/menu.h> | ||||
| #include <wx/gdicmn.h> | ||||
| #include <wx/font.h> | ||||
| #include <wx/colour.h> | ||||
| #include <wx/settings.h> | ||||
| #include <wx/string.h> | ||||
| #include <wx/button.h> | ||||
| #include <wx/bitmap.h> | ||||
| #include <wx/image.h> | ||||
| #include <wx/icon.h> | ||||
| #include <wx/sizer.h> | ||||
| #include <wx/stattext.h> | ||||
| #include <wx/radiobut.h> | ||||
| #include <wx/combobox.h> | ||||
| #include <wx/choice.h> | ||||
| #include <wx/checkbox.h> | ||||
| #include <wx/textctrl.h> | ||||
| #include <wx/sizer.h> | ||||
| #include <wx/panel.h> | ||||
| #include <wx/notebook.h> | ||||
| #include <wx/menu.h> | ||||
| #include <wx/filepicker.h> | ||||
| #include <wx/button.h> | ||||
| #include <wx/scrolwin.h> | ||||
| #include <wx/toolbar.h> | ||||
| #include "visualisationcontrol.h" | ||||
| #include <wx/dataview.h> | ||||
| #include <wx/simplebook.h> | ||||
| #include <wx/frame.h> | ||||
| #include <wx/textctrl.h> | ||||
| #include <wx/dialog.h> | ||||
| #include "fluxviewercontrol.h" | ||||
| #include <wx/scrolbar.h> | ||||
|  | ||||
| @@ -40,91 +46,154 @@ | ||||
| class MainWindowGen : public wxFrame | ||||
| { | ||||
| 	private: | ||||
| 		wxFlexGridSizer* bSizer1; | ||||
|  | ||||
| 	protected: | ||||
| 		VisualisationControl* visualiser; | ||||
| 		wxButton* stopButton; | ||||
| 		wxStaticText* m_staticText4; | ||||
| 		wxComboBox* deviceCombo; | ||||
| 		wxStaticText* m_staticText5; | ||||
| 		wxComboBox* fluxSourceSinkCombo; | ||||
| 		wxStaticText* m_staticText51; | ||||
| 		wxChoice* formatChoice; | ||||
| 		wxCheckBox* highDensityToggle; | ||||
| 		wxNotebook* notebook; | ||||
| 		wxPanel* m_panel1; | ||||
| 		wxTextCtrl* additionalSettingsEntry; | ||||
| 		wxPanel* m_panel2; | ||||
| 		wxTextCtrl* logEntry; | ||||
| 		wxPanel* m_panel3; | ||||
| 		wxTextCtrl* protoConfigEntry; | ||||
| 		wxButton* readFluxButton; | ||||
| 		wxButton* readImageButton; | ||||
| 		wxButton* writeFluxButton; | ||||
| 		wxButton* writeImageButton; | ||||
| 		wxMenuBar* m_menubar1; | ||||
| 		wxMenuBar* menuBar; | ||||
| 		wxMenu* m_menu1; | ||||
| 		wxMenu* m_menu2; | ||||
| 		wxSimplebook* dataNotebook; | ||||
| 		wxScrolledWindow* idlePanel; | ||||
| 		wxStaticText* m_staticText61; | ||||
| 		wxRadioButton* realDiskRadioButton; | ||||
| 		wxPanel* realDiskRadioButtonPanel; | ||||
| 		wxComboBox* deviceCombo; | ||||
| 		wxChoice* driveChoice; | ||||
| 		wxCheckBox* highDensityToggle; | ||||
| 		wxRadioButton* fluxImageRadioButton; | ||||
| 		wxPanel* fluxImageRadioButtonPanel; | ||||
| 		wxFilePickerCtrl* fluxImagePicker; | ||||
| 		wxRadioButton* diskImageRadioButton; | ||||
| 		wxPanel* diskImageRadioButtonPanel; | ||||
| 		wxFilePickerCtrl* diskImagePicker; | ||||
| 		wxStaticText* m_staticText23; | ||||
| 		wxPanel* m_panel11; | ||||
| 		wxChoice* formatChoice; | ||||
| 		wxButton* customConfigurationButton; | ||||
| 		wxStaticText* m_staticText19; | ||||
| 		wxButton* readButton; | ||||
| 		wxButton* writeButton; | ||||
| 		wxButton* browseButton; | ||||
| 		wxPanel* imagePanel; | ||||
| 		wxToolBar* imagerToolbar; | ||||
| 		wxToolBarToolBase* imagerBackTool; | ||||
| 		VisualisationControl* visualiser; | ||||
| 		wxButton* imagerSaveImageButton; | ||||
| 		wxButton* imagerSaveFluxButton; | ||||
| 		wxStaticText* m_staticText4; | ||||
| 		wxButton* imagerGoAgainButton; | ||||
| 		wxPanel* browsePanel; | ||||
| 		wxToolBar* browserToolbar; | ||||
| 		wxToolBarToolBase* browserBackTool; | ||||
| 		wxScrolledWindow* m_scrolledWindow1; | ||||
| 		wxDataViewCtrl* browserView; | ||||
| 		wxDataViewColumn* browserFilenameColumn; | ||||
| 		wxDataViewColumn* browserModeColumn; | ||||
| 		wxDataViewColumn* browserLengthColumn; | ||||
| 		wxDataViewColumn* browserExtraColumn; | ||||
| 		wxButton* browserDiscardButton; | ||||
| 		wxButton* browserCommitButton; | ||||
|  | ||||
| 		// Virtual event handlers, override them in your derived class | ||||
| 		virtual void OnAbout( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnAboutMenuItem( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnExit( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnShowLogWindow( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnShowConfigWindow( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnConfigRadioButtonClicked( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnControlsChanged( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnControlsChanged( wxFileDirPickerEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnCustomConfigurationButton( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnReadButton( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnWriteButton( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnBackButton( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnSaveImageButton( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnSaveFluxButton( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnImagerGoAgainButton( wxCommandEvent& event ) { event.Skip(); } | ||||
|  | ||||
|  | ||||
| 	public: | ||||
|  | ||||
| 		MainWindowGen( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("FluxEngine"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 587,595 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); | ||||
| 		MainWindowGen( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("FluxEngine"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 819,607 ), long style = wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER|wxFULL_REPAINT_ON_RESIZE|wxTAB_TRAVERSAL ); | ||||
|  | ||||
| 		~MainWindowGen(); | ||||
|  | ||||
| }; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| /// Class FluxViewerWindowGen | ||||
| /// Class TextViewerWindowGen | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| class FluxViewerWindowGen : public wxFrame | ||||
| class TextViewerWindowGen : public wxDialog | ||||
| { | ||||
| 	private: | ||||
|  | ||||
| 	protected: | ||||
| 		wxMenuBar* m_menubar2; | ||||
| 		wxMenu* m_menu1; | ||||
| 		FluxViewerControl* fluxviewer; | ||||
| 		wxScrollBar* scrollbar; | ||||
| 		wxTextCtrl* textControl; | ||||
| 		wxStdDialogButtonSizer* m_sdbSizer2; | ||||
| 		wxButton* m_sdbSizer2OK; | ||||
|  | ||||
| 		// Virtual event handlers, override them in your derived class | ||||
| 		virtual void OnExit( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnClose( wxCommandEvent& event ) { event.Skip(); } | ||||
|  | ||||
|  | ||||
| 	public: | ||||
|  | ||||
| 		FluxViewerWindowGen( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Flux Viewer"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); | ||||
| 		TextViewerWindowGen( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 208,143 ), long style = wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); | ||||
|  | ||||
| 		~TextViewerWindowGen(); | ||||
|  | ||||
| }; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| /// Class FluxViewerWindowGen | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| class FluxViewerWindowGen : public wxDialog | ||||
| { | ||||
| 	private: | ||||
|  | ||||
| 	protected: | ||||
| 		FluxViewerControl* fluxviewer; | ||||
| 		wxScrollBar* scrollbar; | ||||
| 		wxStdDialogButtonSizer* m_sdbSizer2; | ||||
| 		wxButton* m_sdbSizer2OK; | ||||
|  | ||||
| 		// Virtual event handlers, override them in your derived class | ||||
| 		virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnClose( wxCommandEvent& event ) { event.Skip(); } | ||||
|  | ||||
|  | ||||
| 	public: | ||||
|  | ||||
| 		FluxViewerWindowGen( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 400,200 ), long style = wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); | ||||
|  | ||||
| 		~FluxViewerWindowGen(); | ||||
|  | ||||
| }; | ||||
|  | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| /// Class HexViewerWindowGen | ||||
| /// Class TextEditorWindowGen | ||||
| /////////////////////////////////////////////////////////////////////////////// | ||||
| class HexViewerWindowGen : public wxFrame | ||||
| class TextEditorWindowGen : public wxDialog | ||||
| { | ||||
| 	private: | ||||
|  | ||||
| 	protected: | ||||
| 		wxMenuBar* m_menubar2; | ||||
| 		wxMenu* m_menu1; | ||||
| 		wxTextCtrl* hexEntry; | ||||
| 		wxTextCtrl* textControl; | ||||
| 		wxStdDialogButtonSizer* m_sdbSizer2; | ||||
| 		wxButton* m_sdbSizer2Save; | ||||
| 		wxButton* m_sdbSizer2Cancel; | ||||
|  | ||||
| 		// Virtual event handlers, override them in your derived class | ||||
| 		virtual void OnExit( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnClose( wxCloseEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); } | ||||
| 		virtual void OnSave( wxCommandEvent& event ) { event.Skip(); } | ||||
|  | ||||
|  | ||||
| 	public: | ||||
|  | ||||
| 		HexViewerWindowGen( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Hex Viewer"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); | ||||
| 		TextEditorWindowGen( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxEmptyString, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); | ||||
|  | ||||
| 		~HexViewerWindowGen(); | ||||
| 		~TextEditorWindowGen(); | ||||
|  | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| #include "globals.h" | ||||
| #include "lib/globals.h" | ||||
| #include "lib/logger.h" | ||||
| #include "gui.h" | ||||
| #include "mainwindow.h" | ||||
| #include "utils.h" | ||||
|  | ||||
| class FluxEngineApp; | ||||
| @@ -8,6 +8,8 @@ class ExecEvent; | ||||
|  | ||||
| static wxSemaphore execSemaphore(0); | ||||
|  | ||||
| wxDEFINE_EVENT(UPDATE_STATE_EVENT, wxCommandEvent); | ||||
|  | ||||
| wxDEFINE_EVENT(EXEC_EVENT_TYPE, ExecEvent); | ||||
| class ExecEvent : public wxThreadEvent | ||||
| { | ||||
| @@ -45,7 +47,7 @@ private: | ||||
| bool FluxEngineApp::OnInit() | ||||
| { | ||||
| 	Bind(EXEC_EVENT_TYPE, &FluxEngineApp::OnExec, this); | ||||
|     _mainWindow = new MainWindow(); | ||||
|     _mainWindow = CreateMainWindow(); | ||||
|     _mainWindow->Show(true); | ||||
|     return true; | ||||
| } | ||||
| @@ -63,13 +65,13 @@ wxThread::ExitCode FluxEngineApp::Entry() | ||||
| 	} | ||||
| 	catch (const EmergencyStopException& e) | ||||
| 	{ | ||||
| 		Logger() << "Emergency stop!\n"; | ||||
| 		Logger() << EmergencyStopMessage(); | ||||
| 	} | ||||
|  | ||||
| 	runOnUiThread( | ||||
| 		[&] { | ||||
| 			_callback = nullptr; | ||||
| 			_mainWindow->UpdateState(); | ||||
| 			SendUpdateEvent(); | ||||
| 		} | ||||
| 	); | ||||
| 	return 0; | ||||
| @@ -87,7 +89,15 @@ void FluxEngineApp::RunOnWorkerThread(std::function<void()> callback) | ||||
| 	emergencyStop = false; | ||||
| 	CreateThread(wxTHREAD_JOINABLE); | ||||
| 	GetThread()->Run(); | ||||
| 	_mainWindow->UpdateState(); | ||||
|  | ||||
| 	SendUpdateEvent(); | ||||
| } | ||||
|  | ||||
| void FluxEngineApp::SendUpdateEvent() | ||||
| { | ||||
| 	auto* event = new wxCommandEvent(UPDATE_STATE_EVENT, 0); | ||||
| 	event->SetEventObject(_mainWindow); | ||||
| 	QueueEvent(event); | ||||
| } | ||||
|  | ||||
| void runOnWorkerThread(std::function<void()> callback) | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,46 +0,0 @@ | ||||
| #ifndef MAINWINDOW_H | ||||
| #define MAINWINDOW_H | ||||
|  | ||||
| #include "layout.h" | ||||
| #include "logger.h" | ||||
| #include <wx/config.h> | ||||
|  | ||||
| class CandidateDevice; | ||||
| class ConfigProto; | ||||
| class DiskFlux; | ||||
|  | ||||
| class MainWindow : public MainWindowGen | ||||
| { | ||||
| public: | ||||
|     MainWindow(); | ||||
|  | ||||
| private: | ||||
|     void OnExit(wxCommandEvent& event); | ||||
| 	void OnStopButton(wxCommandEvent&); | ||||
| 	void OnReadFluxButton(wxCommandEvent&); | ||||
| 	void OnReadImageButton(wxCommandEvent&); | ||||
| 	void OnWriteFluxButton(wxCommandEvent&); | ||||
| 	void OnWriteImageButton(wxCommandEvent&); | ||||
| 	void OnLogMessage(std::shared_ptr<const AnyLogMessage> message); | ||||
| 	void OnTrackSelection(TrackSelectionEvent&); | ||||
| 	void OnControlsChanged(wxCommandEvent&); | ||||
|  | ||||
| public: | ||||
| 	void UpdateState(); | ||||
| 	void UpdateDevices(); | ||||
| 	void PrepareConfig(); | ||||
| 	void ShowConfig(); | ||||
| 	void ApplyCustomSettings(); | ||||
|  | ||||
| private: | ||||
| 	void SetHighDensity(); | ||||
|  | ||||
| private: | ||||
| 	wxConfig _config; | ||||
| 	std::vector<std::unique_ptr<const ConfigProto>> _formats; | ||||
| 	std::vector<std::unique_ptr<const CandidateDevice>> _devices; | ||||
| 	std::shared_ptr<const DiskFlux> _currentDisk; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										60
									
								
								src/gui/texteditorwindow.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/gui/texteditorwindow.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| #include "globals.h" | ||||
| #include "gui.h" | ||||
| #include "layout.h" | ||||
| #include "texteditorwindow.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| wxDEFINE_EVENT(EDITOR_SAVE_EVENT, EditorSaveEvent); | ||||
|  | ||||
| TextEditorWindow::TextEditorWindow( | ||||
|     wxWindow* parent, const std::string& title, const std::string& text): | ||||
|     TextEditorWindowGen(parent) | ||||
| { | ||||
|     auto size = textControl->GetTextExtent("M"); | ||||
|     SetSize(size.Scale(85, 25)); | ||||
|     SetTitle(title); | ||||
|     textControl->SetValue(text); | ||||
| } | ||||
|  | ||||
| TextEditorWindow* TextEditorWindow::Create( | ||||
|     wxWindow* parent, const std::string& title, const std::string& text) | ||||
| { | ||||
|     return new TextEditorWindow(parent, title, text); | ||||
| } | ||||
|  | ||||
| wxTextCtrl* TextEditorWindow::GetTextControl() const | ||||
| { | ||||
|     return textControl; | ||||
| } | ||||
|  | ||||
| void TextEditorWindow::OnClose(wxCloseEvent& event) | ||||
| { | ||||
|     event.Veto(); | ||||
|  | ||||
|     if (textControl->IsModified()) | ||||
|     { | ||||
|         int res = wxMessageBox( | ||||
|             "You have unsaved changes. Do you wish to discard them?", | ||||
|             "Unsaved changes", | ||||
|             wxOK | wxCANCEL | wxICON_WARNING); | ||||
|         if (res != wxOK) | ||||
|             return; | ||||
|     } | ||||
|  | ||||
|     Destroy(); | ||||
| } | ||||
|  | ||||
| void TextEditorWindow::OnSave(wxCommandEvent&) | ||||
| { | ||||
|     EditorSaveEvent event(EDITOR_SAVE_EVENT, GetId()); | ||||
|     event.SetEventObject(this); | ||||
|     event.text = textControl->GetValue(); | ||||
|     ProcessWindowEvent(event); | ||||
|  | ||||
|     Destroy(); | ||||
| } | ||||
|  | ||||
| void TextEditorWindow::OnCancel(wxCommandEvent&) | ||||
| { | ||||
|     Destroy(); | ||||
| } | ||||
							
								
								
									
										41
									
								
								src/gui/texteditorwindow.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/gui/texteditorwindow.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| #ifndef TEXTEDITORWINDOW_H | ||||
| #define TEXTEDITORWINDOW_H | ||||
|  | ||||
| #include "layout.h" | ||||
|  | ||||
| class EditorSaveEvent : public wxEvent | ||||
| { | ||||
| public: | ||||
|     EditorSaveEvent(wxEventType eventType, int winId): wxEvent(winId, eventType) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     wxEvent* Clone() const | ||||
|     { | ||||
|         return new EditorSaveEvent(*this); | ||||
|     } | ||||
|  | ||||
|     std::string text; | ||||
| }; | ||||
|  | ||||
| wxDECLARE_EVENT(EDITOR_SAVE_EVENT, EditorSaveEvent); | ||||
|  | ||||
| class TextEditorWindow : public TextEditorWindowGen | ||||
| { | ||||
| public: | ||||
|     TextEditorWindow( | ||||
|         wxWindow* parent, const std::string& title, const std::string& text); | ||||
|  | ||||
|     static TextEditorWindow* Create( | ||||
|         wxWindow* parent, const std::string& title, const std::string& text); | ||||
|  | ||||
| public: | ||||
|     wxTextCtrl* GetTextControl() const; | ||||
|  | ||||
| private: | ||||
|     void OnClose(wxCloseEvent& event) override; | ||||
|     void OnSave(wxCommandEvent& event) override; | ||||
|     void OnCancel(wxCommandEvent& event) override; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										39
									
								
								src/gui/textviewerwindow.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/gui/textviewerwindow.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| #include "globals.h" | ||||
| #include "gui.h" | ||||
| #include "layout.h" | ||||
| #include "textviewerwindow.h" | ||||
| #include "fmt/format.h" | ||||
|  | ||||
| TextViewerWindow::TextViewerWindow(wxWindow* parent, | ||||
|     const std::string& title, | ||||
|     const std::string& text, | ||||
|     bool autodestroy): | ||||
|     TextViewerWindowGen(parent), | ||||
|     _autodestroy(autodestroy) | ||||
| { | ||||
|     auto size = textControl->GetTextExtent("M"); | ||||
|     SetSize(size.Scale(85, 25)); | ||||
|     SetTitle(title); | ||||
|     textControl->SetValue(text); | ||||
| } | ||||
|  | ||||
| TextViewerWindow* TextViewerWindow::Create(wxWindow* parent, | ||||
|     const std::string& title, | ||||
|     const std::string& text, | ||||
|     bool autodestroy) | ||||
| { | ||||
|     return new TextViewerWindow(parent, title, text, autodestroy); | ||||
| } | ||||
|  | ||||
| wxTextCtrl* TextViewerWindow::GetTextControl() const | ||||
| { | ||||
|     return textControl; | ||||
| } | ||||
|  | ||||
| void TextViewerWindow::OnClose(wxCloseEvent& event) | ||||
| { | ||||
|     if (_autodestroy) | ||||
|         Destroy(); | ||||
|     else | ||||
|         Hide(); | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/gui/textviewerwindow.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/gui/textviewerwindow.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| #ifndef TEXTVIEWERWINDOW_H | ||||
| #define TEXTVIEWERWINDOW_H | ||||
|  | ||||
| #include "layout.h" | ||||
|  | ||||
| class TextViewerWindow : public TextViewerWindowGen | ||||
| { | ||||
| public: | ||||
|     TextViewerWindow(wxWindow* parent, | ||||
|         const std::string& title, | ||||
|         const std::string& text, | ||||
|         bool autodestroy); | ||||
|  | ||||
|     static TextViewerWindow* Create(wxWindow* parent, | ||||
|         const std::string& title, | ||||
|         const std::string& text, | ||||
|         bool autodestroy = true); | ||||
|  | ||||
| public: | ||||
|     wxTextCtrl* GetTextControl() const; | ||||
|  | ||||
| private: | ||||
|     void OnClose(wxCloseEvent& event); | ||||
|  | ||||
| private: | ||||
|     bool _autodestroy; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
| @@ -11,8 +11,6 @@ | ||||
| #define TICK 3 | ||||
| #define TRACKS 82 | ||||
|  | ||||
| #define SECTORSIZE 5 | ||||
|  | ||||
| wxDEFINE_EVENT(TRACK_SELECTION_EVENT, TrackSelectionEvent); | ||||
|  | ||||
| DECLARE_COLOUR(AXIS, 128, 128, 128); | ||||
| @@ -30,15 +28,17 @@ VisualisationControl::VisualisationControl(wxWindow* parent, | ||||
|     long style): | ||||
|     wxWindow(parent, id, pos, size, style, "VisualisationControl") | ||||
| { | ||||
| 	SetDoubleBuffered(true); | ||||
|     SetDoubleBuffered(true); | ||||
| } | ||||
|  | ||||
| // clang-format off | ||||
| wxBEGIN_EVENT_TABLE(VisualisationControl, wxPanel) | ||||
|     EVT_PAINT(VisualisationControl::OnPaint) | ||||
| 	EVT_MOTION(VisualisationControl::OnMotion) | ||||
| 	EVT_LEFT_DOWN(VisualisationControl::OnLeftDown) | ||||
| 	EVT_LEAVE_WINDOW(VisualisationControl::OnLeaveWindow) | ||||
| wxEND_EVENT_TABLE() | ||||
| wxEND_EVENT_TABLE(); | ||||
| // clang-format on | ||||
|  | ||||
| void VisualisationControl::OnPaint(wxPaintEvent&) | ||||
| { | ||||
| @@ -46,17 +46,20 @@ void VisualisationControl::OnPaint(wxPaintEvent&) | ||||
|     int w = size.GetWidth(); | ||||
|     int w2 = w / 2; | ||||
|     int h = size.GetHeight(); | ||||
|     int h2 = h / 2; | ||||
|  | ||||
|     int centrey = h * 1.5; | ||||
|     int outerradius = centrey - BORDER; | ||||
|     int innerradius = centrey - h + BORDER; | ||||
|     int scalesize = TRACKS * SECTORSIZE; | ||||
|     int scaletop = h / 2 - scalesize / 2; | ||||
|     int scalesize = h - BORDER * 4; | ||||
|     int sectorsize = scalesize / TRACKS; | ||||
|     scalesize = sectorsize * TRACKS; | ||||
|     int scaletop = h2 - scalesize / 2; | ||||
|     int scalebottom = scaletop + scalesize - 1; | ||||
|     int outerradius = centrey - scaletop + BORDER; | ||||
|     int innerradius = centrey - scalebottom - BORDER; | ||||
|  | ||||
|     wxPaintDC dc(this); | ||||
| 	dc.SetBackground(*wxWHITE_BRUSH); | ||||
| 	dc.Clear(); | ||||
|     dc.SetBackground(*wxWHITE_BRUSH); | ||||
|     dc.Clear(); | ||||
|  | ||||
|     dc.SetPen(*wxBLACK_PEN); | ||||
|     dc.SetBrush(*wxLIGHT_GREY_BRUSH); | ||||
| @@ -70,33 +73,33 @@ void VisualisationControl::OnPaint(wxPaintEvent&) | ||||
|     if (_mode != VISMODE_NOTHING) | ||||
|     { | ||||
|         if (_mode == VISMODE_READING) | ||||
| 		{ | ||||
| 			dc.SetPen(READ_ARROW_PEN); | ||||
| 			dc.SetBrush(READ_ARROW_BRUSH); | ||||
| 		} | ||||
|         { | ||||
|             dc.SetPen(READ_ARROW_PEN); | ||||
|             dc.SetBrush(READ_ARROW_BRUSH); | ||||
|         } | ||||
|         else if (_mode == VISMODE_WRITING) | ||||
| 		{ | ||||
| 			dc.SetPen(WRITE_ARROW_PEN); | ||||
| 			dc.SetBrush(WRITE_ARROW_BRUSH); | ||||
| 		} | ||||
|         { | ||||
|             dc.SetPen(WRITE_ARROW_PEN); | ||||
|             dc.SetBrush(WRITE_ARROW_BRUSH); | ||||
|         } | ||||
|  | ||||
|         int factor = (_head == 0) ? -1 : 1; | ||||
|  | ||||
|         int y = scaletop + _track * SECTORSIZE; | ||||
| 		wxPoint points[] = { | ||||
| 			{ w2 + factor*TICK, y-1 }, | ||||
| 			{ w2 + factor*TICK, y+SECTORSIZE-1 }, | ||||
| 			{ w2 + factor*TICK*2, y+SECTORSIZE/2 } | ||||
| 		}; | ||||
| 		dc.DrawPolygon(3, points); | ||||
|         int y = scaletop + _track * sectorsize; | ||||
|         wxPoint points[] = { | ||||
|             {w2 + factor * TICK,     y - 1             }, | ||||
|             {w2 + factor * TICK,     y + sectorsize - 1}, | ||||
|             {w2 + factor * TICK * 2, y + sectorsize / 2} | ||||
|         }; | ||||
|         dc.DrawPolygon(3, points); | ||||
|     } | ||||
|  | ||||
|     for (int track = 0; track <= TRACKS; track++) | ||||
|     { | ||||
|         int y = scaletop + track * SECTORSIZE; | ||||
|         int y = scaletop + track * sectorsize; | ||||
|         dc.SetBrush(AXIS_BRUSH); | ||||
|         dc.SetPen(AXIS_PEN); | ||||
|         dc.DrawLine({w2 - TICK, y-1}, {w2 + TICK, y-1}); | ||||
|         dc.DrawLine({w2 - TICK, y - 1}, {w2 + TICK, y - 1}); | ||||
|  | ||||
|         auto drawSectors = [&](int head) | ||||
|         { | ||||
| @@ -130,11 +133,11 @@ void VisualisationControl::OnPaint(wxPaintEvent&) | ||||
|  | ||||
|                 if (head == 0) | ||||
|                     dc.DrawRectangle( | ||||
|                         {w2 - x * SECTORSIZE - (SECTORSIZE - 1), y}, | ||||
|                         {SECTORSIZE - 1, SECTORSIZE - 1}); | ||||
|                         {w2 - x * sectorsize - (sectorsize - 1), y}, | ||||
|                         {sectorsize - 1, sectorsize - 1}); | ||||
|                 else | ||||
|                     dc.DrawRectangle({w2 + x * SECTORSIZE + 1, y}, | ||||
|                         {SECTORSIZE - 1, SECTORSIZE - 1}); | ||||
|                     dc.DrawRectangle({w2 + x * sectorsize + 1, y}, | ||||
|                         {sectorsize - 1, sectorsize - 1}); | ||||
|                 x++; | ||||
|             } | ||||
|         }; | ||||
| @@ -143,42 +146,59 @@ void VisualisationControl::OnPaint(wxPaintEvent&) | ||||
|         drawSectors(1); | ||||
|     } | ||||
|  | ||||
| 	if (_selectedTrack != -1) | ||||
| 	{ | ||||
| 		int x = (_selectedHead ? (w2-1) : 0) + SECTORSIZE; | ||||
|         int y = scaletop + _selectedTrack * SECTORSIZE - 1; | ||||
| 		int bw = w/2 - SECTORSIZE*2 + 2; | ||||
| 		int bh = SECTORSIZE + 3; | ||||
| 		dc.SetPen(SELECTION_BOX_PEN); | ||||
| 		dc.SetBrush(*wxTRANSPARENT_BRUSH); | ||||
| 		dc.DrawRectangle({x, y-1, bw, bh}); | ||||
|     if (_selectedTrack != -1) | ||||
|     { | ||||
|         key_t key = {_selectedTrack, _selectedHead}; | ||||
|         int sectorCount = 0; | ||||
|         for (auto it = _sectors.lower_bound(key); | ||||
|              it != _sectors.upper_bound(key); | ||||
|              it++) | ||||
|             sectorCount++; | ||||
|  | ||||
| 		static wxFont font(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); | ||||
| 		dc.SetFont(font); | ||||
| 		dc.SetBackgroundMode(wxTRANSPARENT); | ||||
| 		dc.SetTextForeground(*wxBLACK); | ||||
|         if (sectorCount != 0) | ||||
|         { | ||||
|             dc.SetPen(SELECTION_BOX_PEN); | ||||
|             dc.SetBrush(*wxTRANSPARENT_BRUSH); | ||||
|             int bw = sectorCount * sectorsize + 3; | ||||
|             int bh = sectorsize + 3; | ||||
|             int y = scaletop + _selectedTrack * sectorsize - 1; | ||||
|             if (_selectedHead == 0) | ||||
|             { | ||||
|                 int x = w2 - bw - sectorsize + 2; | ||||
|                 dc.DrawRectangle({x, y - 1, bw, bh}); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 int x = w2 - 1 + sectorsize; | ||||
|                 dc.DrawRectangle({x, y - 1, bw, bh}); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| 		auto centreText = [&](const std::string& text, int y) | ||||
| 		{ | ||||
| 			auto size = dc.GetTextExtent(text); | ||||
| 			dc.DrawText(text, { w2 - size.x/2 , y }); | ||||
| 		}; | ||||
|         static wxFont font( | ||||
|             8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); | ||||
|         dc.SetFont(font); | ||||
|         dc.SetBackgroundMode(wxTRANSPARENT); | ||||
|         dc.SetTextForeground(*wxBLACK); | ||||
|  | ||||
| 		centreText( | ||||
| 			fmt::format("physical: {}.{}", _selectedTrack, _selectedHead), | ||||
| 			scalebottom + 5); | ||||
|         auto centreText = [&](const std::string& text, int y) | ||||
|         { | ||||
|             auto size = dc.GetTextExtent(text); | ||||
|             dc.DrawText(text, {w2 - size.x / 2, y}); | ||||
|         }; | ||||
|  | ||||
|         centreText( | ||||
|             fmt::format("physical: {}.{}", _selectedTrack, _selectedHead), | ||||
|             h - 25); | ||||
|  | ||||
| 		key_t key = {_selectedTrack, _selectedHead}; | ||||
|         auto it = _tracks.find(key); | ||||
| 		std::string logicalText = "logical: (none)"; | ||||
| 		if (it != _tracks.end()) | ||||
| 			logicalText = fmt::format( | ||||
| 					"logical: {}.{}", | ||||
| 					it->second->location.logicalTrack, | ||||
| 					it->second->location.head); | ||||
|         std::string logicalText = "logical: (none)"; | ||||
|         if (it != _tracks.end()) | ||||
|             logicalText = fmt::format("logical: {}.{}", | ||||
|                 it->second->location.logicalTrack, | ||||
|                 it->second->location.head); | ||||
|  | ||||
| 		centreText(logicalText, scalebottom + 15); | ||||
| 	} | ||||
|         centreText(logicalText, h - 35); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void VisualisationControl::OnMotion(wxMouseEvent& event) | ||||
| @@ -189,47 +209,49 @@ void VisualisationControl::OnMotion(wxMouseEvent& event) | ||||
|     int h = size.GetHeight(); | ||||
|  | ||||
|     int centrey = h * 1.5; | ||||
|     int scalesize = TRACKS * SECTORSIZE; | ||||
|     int scalesize = h - BORDER * 4; | ||||
|     int sectorsize = scalesize / TRACKS; | ||||
|     scalesize = sectorsize * TRACKS; | ||||
|     int scaletop = h / 2 - scalesize / 2; | ||||
|     int scalebottom = scaletop + scalesize - 1; | ||||
|  | ||||
| 	int headno = event.GetX() > w2; | ||||
|     int headno = event.GetX() > w2; | ||||
|  | ||||
| 	int trackno = (event.GetY() - scaletop) / SECTORSIZE; | ||||
| 	if ((trackno < 0) || (trackno >= TRACKS)) | ||||
| 		trackno = -1; | ||||
| 	if ((_selectedHead != headno) || (_selectedTrack != trackno)) | ||||
| 	{ | ||||
| 		_selectedTrack = trackno; | ||||
| 		_selectedHead = headno; | ||||
| 		Refresh(); | ||||
| 	} | ||||
|     int trackno = (event.GetY() - scaletop) / sectorsize; | ||||
|     if ((trackno < 0) || (trackno >= TRACKS)) | ||||
|         trackno = -1; | ||||
|     if ((_selectedHead != headno) || (_selectedTrack != trackno)) | ||||
|     { | ||||
|         _selectedTrack = trackno; | ||||
|         _selectedHead = headno; | ||||
|         Refresh(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void VisualisationControl::OnLeftDown(wxMouseEvent& event) | ||||
| { | ||||
| 	OnMotion(event); | ||||
|     OnMotion(event); | ||||
|  | ||||
| 	if ((_selectedHead != -1) && (_selectedTrack != -1)) | ||||
| 	{ | ||||
| 		key_t key = {_selectedTrack, _selectedHead}; | ||||
|     if ((_selectedHead != -1) && (_selectedTrack != -1)) | ||||
|     { | ||||
|         key_t key = {_selectedTrack, _selectedHead}; | ||||
|         auto it = _tracks.find(key); | ||||
| 		if (it != _tracks.end()) | ||||
| 		{ | ||||
| 			TrackSelectionEvent event(TRACK_SELECTION_EVENT, GetId()); | ||||
| 			event.SetEventObject(this); | ||||
| 			event.trackFlux = it->second; | ||||
| 			ProcessWindowEvent(event); | ||||
| 		} | ||||
| 	} | ||||
|         if (it != _tracks.end()) | ||||
|         { | ||||
|             TrackSelectionEvent event(TRACK_SELECTION_EVENT, GetId()); | ||||
|             event.SetEventObject(this); | ||||
|             event.trackFlux = it->second; | ||||
|             ProcessWindowEvent(event); | ||||
|         } | ||||
|     } | ||||
|     else | ||||
|         event.Skip(); | ||||
| } | ||||
|  | ||||
| void VisualisationControl::OnLeaveWindow(wxMouseEvent&) | ||||
| { | ||||
| 	_selectedTrack = _selectedHead = -1; | ||||
| 	Refresh(); | ||||
|     _selectedTrack = _selectedHead = -1; | ||||
|     Refresh(); | ||||
| } | ||||
|  | ||||
| void VisualisationControl::SetMode(int track, int head, int mode) | ||||
| @@ -243,14 +265,14 @@ void VisualisationControl::SetMode(int track, int head, int mode) | ||||
| void VisualisationControl::Clear() | ||||
| { | ||||
|     _sectors.clear(); | ||||
| 	_tracks.clear(); | ||||
|     _tracks.clear(); | ||||
|     Refresh(); | ||||
| } | ||||
|  | ||||
| void VisualisationControl::SetTrackData(std::shared_ptr<const TrackFlux> track) | ||||
| { | ||||
|     key_t key = {track->location.physicalTrack, track->location.head}; | ||||
| 	_tracks[key] = track; | ||||
|     _tracks[key] = track; | ||||
|     _sectors.erase(key); | ||||
|     for (auto& sector : track->sectors) | ||||
|         _sectors.insert({key, sector}); | ||||
| @@ -260,18 +282,18 @@ void VisualisationControl::SetTrackData(std::shared_ptr<const TrackFlux> track) | ||||
|  | ||||
| void VisualisationControl::SetDiskData(std::shared_ptr<const DiskFlux> disk) | ||||
| { | ||||
| 	_sectors.clear(); | ||||
| 	for (const auto& track : disk->tracks) | ||||
| 	{ | ||||
| 		key_t key = {track->location.physicalTrack, track->location.head}; | ||||
| 		_tracks[key] = track; | ||||
| 	} | ||||
|     _sectors.clear(); | ||||
|     for (const auto& track : disk->tracks) | ||||
|     { | ||||
|         key_t key = {track->location.physicalTrack, track->location.head}; | ||||
|         _tracks[key] = track; | ||||
|     } | ||||
|  | ||||
| 	for (const auto& sector : *(disk->image)) | ||||
| 	{ | ||||
| 		key_t key = {sector->physicalTrack, sector->physicalHead}; | ||||
| 		_sectors.insert({key, sector}); | ||||
| 	} | ||||
|     for (const auto& sector : *(disk->image)) | ||||
|     { | ||||
|         key_t key = {sector->physicalTrack, sector->physicalHead}; | ||||
|         _sectors.insert({key, sector}); | ||||
|     } | ||||
|  | ||||
|     Refresh(); | ||||
| } | ||||
|   | ||||
| @@ -9,23 +9,27 @@ class Sector; | ||||
| class DiskFlux; | ||||
| class TrackFlux; | ||||
|  | ||||
| enum { | ||||
| 	VISMODE_NOTHING, | ||||
| 	VISMODE_READING, | ||||
| 	VISMODE_WRITING | ||||
| enum | ||||
| { | ||||
|     VISMODE_NOTHING, | ||||
|     VISMODE_READING, | ||||
|     VISMODE_WRITING | ||||
| }; | ||||
|  | ||||
| class TrackSelectionEvent : public wxEvent | ||||
| { | ||||
| public: | ||||
| 	TrackSelectionEvent(wxEventType eventType, int winId): | ||||
| 		wxEvent(winId, eventType) | ||||
| 	{} | ||||
|     TrackSelectionEvent(wxEventType eventType, int winId): | ||||
|         wxEvent(winId, eventType) | ||||
|     { | ||||
|     } | ||||
|  | ||||
| 	wxEvent *Clone() const | ||||
| 	{ return new TrackSelectionEvent(*this); } | ||||
|     wxEvent* Clone() const | ||||
|     { | ||||
|         return new TrackSelectionEvent(*this); | ||||
|     } | ||||
|  | ||||
| 	std::shared_ptr<const TrackFlux> trackFlux; | ||||
|     std::shared_ptr<const TrackFlux> trackFlux; | ||||
| }; | ||||
|  | ||||
| wxDECLARE_EVENT(TRACK_SELECTION_EVENT, TrackSelectionEvent); | ||||
| @@ -40,27 +44,27 @@ public: | ||||
|         long style = 0); | ||||
|  | ||||
| public: | ||||
| 	void Clear(); | ||||
| 	void SetMode(int head, int track, int mode); | ||||
| 	void SetTrackData(std::shared_ptr<const TrackFlux> track); | ||||
| 	void SetDiskData(std::shared_ptr<const DiskFlux> disk); | ||||
|     void Clear(); | ||||
|     void SetMode(int head, int track, int mode); | ||||
|     void SetTrackData(std::shared_ptr<const TrackFlux> track); | ||||
|     void SetDiskData(std::shared_ptr<const DiskFlux> disk); | ||||
|  | ||||
| private: | ||||
| 	void OnPaint(wxPaintEvent& evt); | ||||
| 	void OnMotion(wxMouseEvent& evt); | ||||
| 	void OnLeftDown(wxMouseEvent& evt); | ||||
| 	void OnLeaveWindow(wxMouseEvent& evt); | ||||
|     void OnPaint(wxPaintEvent& evt); | ||||
|     void OnMotion(wxMouseEvent& evt); | ||||
|     void OnLeftDown(wxMouseEvent& evt); | ||||
|     void OnLeaveWindow(wxMouseEvent& evt); | ||||
|  | ||||
| private: | ||||
| 	typedef std::pair<unsigned, unsigned> key_t; | ||||
|     typedef std::pair<unsigned, unsigned> key_t; | ||||
|  | ||||
| 	int _head; | ||||
| 	int _track; | ||||
| 	int _mode = VISMODE_NOTHING; | ||||
| 	int _selectedHead = -1; | ||||
| 	int _selectedTrack = -1; | ||||
| 	std::multimap<key_t, std::shared_ptr<const Sector>> _sectors; | ||||
| 	std::map<key_t, std::shared_ptr<const TrackFlux>> _tracks; | ||||
|     int _head; | ||||
|     int _track; | ||||
|     int _mode = VISMODE_NOTHING; | ||||
|     int _selectedHead = -1; | ||||
|     int _selectedTrack = -1; | ||||
|     std::multimap<key_t, std::shared_ptr<const Sector>> _sectors; | ||||
|     std::map<key_t, std::shared_ptr<const TrackFlux>> _tracks; | ||||
|     wxDECLARE_EVENT_TABLE(); | ||||
| }; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user