Exemple #1
0
        private static void Main(string[] args)
        {
            var configuration = new ConfigurationBuilder()
                                .AddJsonFile("appsettings.json")
                                .Build();

            _appSettings = new AppSettings
            {
                TargetPatches = configuration.GetSection(nameof(AppSettings.TargetPatches)).GetChildren().Select(targetPatch => new TargetPatch
                {
                    Patch        = Enum.Parse <GamePatch>(targetPatch.GetSection(nameof(TargetPatch.Patch)).Value),
                    GameDataPath = targetPatch.GetSection(nameof(TargetPatch.GameDataPath)).Value,
                }).ToList(),
            };

            _watcher          = new FileSystemWatcher();
            _watcher.Created += OnWatchedFileEvent;
            _watcher.Renamed += OnWatchedFileEvent;
            _watcher.Deleted += OnWatchedFileEvent;

            var form = new Form();

            form.Size        = new Size(1280, 720);
            form.MinimumSize = new Size(400, 300);
            form.Text        = Title;

            var splitContainer = new SplitContainer
            {
                Dock = DockStyle.Fill,
            };

            _archiveInput = new TextBox
            {
                PlaceholderText = "Input map or campaign...",
            };

            _openCloseArchiveButton = new Button
            {
                Text    = "Open archive",
                Enabled = false,
            };

            _diagnosticsDisplay = new TextBox
            {
                Multiline  = true,
                ReadOnly   = true,
                Dock       = DockStyle.Fill,
                ScrollBars = ScrollBars.Vertical,
            };

            _progressBar = new TextProgressBar
            {
                Dock       = DockStyle.Bottom,
                Style      = ProgressBarStyle.Continuous,
                VisualMode = TextProgressBar.ProgressBarDisplayMode.CustomText,
                Visible    = false,
            };

            _openArchiveWorker = new BackgroundWorker
            {
                WorkerReportsProgress      = true,
                WorkerSupportsCancellation = false,
            };

            _openArchiveWorker.DoWork             += OpenArchiveBackgroundWork;
            _openArchiveWorker.ProgressChanged    += OpenArchiveProgressChanged;
            _openArchiveWorker.RunWorkerCompleted += OpenArchiveCompleted;

            _saveArchiveWorker = new BackgroundWorker
            {
                WorkerReportsProgress      = true,
                WorkerSupportsCancellation = false,
            };

            _saveArchiveWorker.DoWork             += SaveArchiveBackgroundWork;
            _saveArchiveWorker.ProgressChanged    += SaveArchiveProgressChanged;
            _saveArchiveWorker.RunWorkerCompleted += SaveArchiveCompleted;

            _adaptAllButton = new Button
            {
                Text = "Adapt all",
            };

            _adaptAllButton.Size    = _adaptAllButton.PreferredSize;
            _adaptAllButton.Enabled = false;

            _saveAsButton = new Button
            {
                Text = "Save As...",
            };

            _saveAsButton.Size    = _saveAsButton.PreferredSize;
            _saveAsButton.Enabled = false;

            _targetPatchesComboBox = new ComboBox
            {
                Enabled       = false,
                DropDownStyle = ComboBoxStyle.DropDownList,
                Width         = 120,
            };

            _targetPatchesComboBox.Items.AddRange(_appSettings.TargetPatches.OrderByDescending(targetPatch => targetPatch.Patch).Select(targetPatch => (object)targetPatch.Patch).ToArray());
            if (_targetPatchesComboBox.Items.Count == 1)
            {
                _targetPatchesComboBox.SelectedIndex = 0;
            }

            _targetPatchesComboBox.SelectedIndexChanged += (s, e) =>
            {
                _targetPatch            = (GamePatch?)_targetPatchesComboBox.SelectedItem;
                _adaptAllButton.Enabled = _targetPatch.HasValue && _fileList.Items.Count > 0;
            };

            _targetPatchesComboBox.FormattingEnabled = true;
            _targetPatchesComboBox.Format           += (s, e) =>
            {
                if (e.ListItem is GamePatch gamePatch)
                {
                    e.Value = gamePatch.ToString().Replace('_', '.');
                }
            };

            _archiveInput.TextChanged += OnArchiveInputTextChanged;

            _archiveInputBrowseButton = new Button
            {
                Text = "Browse",
            };

            _archiveInputBrowseButton.Size   = _archiveInputBrowseButton.PreferredSize;
            _archiveInputBrowseButton.Click += (s, e) =>
            {
                var openFileDialog = new OpenFileDialog
                {
                    CheckFileExists = false,
                };
                openFileDialog.Filter = string.Join('|', new[]
                {
                    "Warcraft III archive|*.w3m;*.w3x;*.w3n",
                    "Warcraft III map|*.w3m;*.w3x",
                    "Warcraft III campaign|*.w3n",
                    "All files|*.*",
                });
                var openFileDialogResult = openFileDialog.ShowDialog();
                if (openFileDialogResult == DialogResult.OK)
                {
                    _archiveInput.Text = openFileDialog.FileName;
                }
            };

            _fileList = new ListView
            {
                Dock = DockStyle.Fill,
            };

            _fileListSorter = new FileListSorter(_fileList);

            _fileList.ListViewItemSorter = _fileListSorter;
            _fileList.ColumnClick       += _fileListSorter.Sort;

            _fileList.View = View.Details;
            _fileList.Columns.AddRange(new[]
            {
                new ColumnHeader {
                    Text = "Status", Width = 102
                },
                new ColumnHeader {
                    Text = "FileName", Width = 300
                },
                new ColumnHeader {
                    Text = "FileType", Width = 130
                },
                new ColumnHeader {
                    Text = "Archive", Width = 87
                },
            });

            _fileList.FullRowSelect = true;
            _fileList.MultiSelect   = true;

            _fileList.HeaderStyle = ColumnHeaderStyle.Clickable;

            _fileList.SmallImageList = new ImageList();
            var statusColors = new Dictionary <MapFileStatus, Color>
            {
                { MapFileStatus.Adapted, Color.LimeGreen },
                { MapFileStatus.AdapterError, Color.Red },
                { MapFileStatus.Compatible, Color.ForestGreen },
                { MapFileStatus.ConfigError, Color.DarkSlateBlue },
                { MapFileStatus.Incompatible, Color.Yellow },
                { MapFileStatus.Locked, Color.OrangeRed },
                { MapFileStatus.Modified, Color.Blue },
                { MapFileStatus.ParseError, Color.Maroon },
                { MapFileStatus.Pending, Color.LightSkyBlue },
                { MapFileStatus.Removed, Color.DarkSlateGray },
                { MapFileStatus.Unadaptable, Color.IndianRed },
                { MapFileStatus.Unknown, Color.DarkViolet },
            };

            foreach (var status in Enum.GetValues(typeof(MapFileStatus)))
            {
                _fileList.SmallImageList.Images.Add(new Bitmap(16, 16).WithSolidColor(statusColors[(MapFileStatus)status]));
            }

            var fileListContextMenu = new ContextMenuStrip
            {
            };

            _editContextButton         = new ToolStripButton("Edit");
            _editContextButton.Enabled = false;
            _editContextButton.Click  += OnClickEditSelected;

            _adaptContextButton         = new ToolStripButton("Adapt");
            _adaptContextButton.Enabled = false;
            _adaptContextButton.Click  += OnClickAdaptSelected;

            _removeContextButton         = new ToolStripButton("Remove");
            _removeContextButton.Enabled = false;
            _removeContextButton.Click  += OnClickRemoveSelected;

            fileListContextMenu.Items.AddRange(new[]
            {
                _adaptContextButton,
                _editContextButton,
                _removeContextButton,
            });

            _fileList.ContextMenuStrip = fileListContextMenu;

            _openCloseArchiveButton.Size   = _openCloseArchiveButton.PreferredSize;
            _openCloseArchiveButton.Click += OnClickOpenCloseMap;

            _adaptAllButton.Click += (s, e) =>
            {
                _targetPatchesComboBox.Enabled = false;
                var parentsToUpdate = new HashSet <ItemTag>();
                for (var i = 0; i < _fileList.Items.Count; i++)
                {
                    var item = _fileList.Items[i];
                    var tag  = item.GetTag();

                    var adapter = tag.Adapter;
                    if (adapter != null && (tag.Status == MapFileStatus.Pending || tag.Status == MapFileStatus.Modified))
                    {
                        tag.CurrentStream.Position = 0;
                        var adaptResult = adapter.AdaptFile(tag.CurrentStream, GetTargetPatch(_targetPatch.Value), tag.GetOriginPatch(_originPatch.Value));
                        tag.UpdateAdaptResult(adaptResult);

                        if (tag.Parent != null)
                        {
                            parentsToUpdate.Add(tag.Parent);
                        }
                    }
                }

                foreach (var parent in parentsToUpdate)
                {
                    parent.ListViewItem.Update();
                }

                UpdateDiagnosticsDisplay();
            };

            _fileList.KeyDown += (s, e) =>
            {
                if (e.KeyCode == Keys.Delete)
                {
                    OnClickRemoveSelected(s, e);
                }
            };

            _fileList.SelectedIndexChanged += OnFileSelectionChanged;

            _fileList.ItemActivate += OnClickEditSelected;

            _saveAsButton.Click += (s, e) =>
            {
                var saveFileDialog = new SaveFileDialog
                {
                    OverwritePrompt = true,
                    CreatePrompt    = false,
                };

                var saveFileDialogResult = saveFileDialog.ShowDialog();
                if (saveFileDialogResult == DialogResult.OK)
                {
                    SaveArchive(saveFileDialog.FileName);
                }
            };

            var flowLayout = new FlowLayoutPanel
            {
                Dock          = DockStyle.Top,
                FlowDirection = FlowDirection.TopDown,
                Width         = 640,
            };

            var inputArchiveFlowLayout = new FlowLayoutPanel
            {
                FlowDirection = FlowDirection.LeftToRight,
            };

            var buttonsFlowLayout = new FlowLayoutPanel
            {
                FlowDirection = FlowDirection.LeftToRight,
            };

            var targetPatchLabel = new Label
            {
                Text      = "Target patch",
                TextAlign = ContentAlignment.BottomRight,
            };

            inputArchiveFlowLayout.AddControls(_archiveInput, _archiveInputBrowseButton, _openCloseArchiveButton);
            buttonsFlowLayout.AddControls(_adaptAllButton, _saveAsButton, targetPatchLabel, _targetPatchesComboBox);
            flowLayout.AddControls(inputArchiveFlowLayout, buttonsFlowLayout);

            splitContainer.Panel1.AddControls(_diagnosticsDisplay, flowLayout);
            splitContainer.Panel2.AddControls(_fileList);
            form.AddControls(splitContainer, _progressBar);

            targetPatchLabel.Size = targetPatchLabel.PreferredSize;

            splitContainer.Panel1.SizeChanged += (s, e) =>
            {
                var width = splitContainer.Panel1.Width;
                _archiveInput.Width = (width > 360 ? 360 : width) - 10;

                inputArchiveFlowLayout.Size = inputArchiveFlowLayout.GetPreferredSize(new Size(width, 0));
                buttonsFlowLayout.Size      = buttonsFlowLayout.GetPreferredSize(new Size(width, 0));
                flowLayout.Height
                    = inputArchiveFlowLayout.Margin.Top + inputArchiveFlowLayout.Height + inputArchiveFlowLayout.Margin.Bottom
                      + buttonsFlowLayout.Margin.Top + buttonsFlowLayout.Height + buttonsFlowLayout.Margin.Bottom;
            };

            splitContainer.SplitterDistance = 640 - splitContainer.SplitterWidth;
            splitContainer.Panel1MinSize    = 200;

            form.FormClosing += (s, e) =>
            {
                _archive?.Dispose();
                _openArchiveWorker?.Dispose();
                _saveArchiveWorker?.Dispose();
                _fileSelectionChangedEventTimer?.Dispose();
            };

            form.ShowDialog();
        }
Exemple #2
0
        public ScriptEditForm(RegexDiagnostic[] diagnostics)
        {
            _window             = new Form();
            _window.WindowState = FormWindowState.Maximized;

            _script = new RichTextBox
            {
                Width      = _window.Width - 500,
                Dock       = DockStyle.Right,
                Multiline  = true,
                ScrollBars = RichTextBoxScrollBars.Both,
                ZoomFactor = 1f,
                Font       = new Font("Consolas", 12f, FontStyle.Regular),
                DetectUrls = false,
                WordWrap   = false,
            };

            _diagnosticsView = new ListView
            {
                Height        = _window.Height - 150,
                Dock          = DockStyle.Top,
                FullRowSelect = true,
                MultiSelect   = false,
                HeaderStyle   = ColumnHeaderStyle.Clickable,
            };

            _diagnosticsView.View = View.Details;
            _diagnosticsView.Columns.AddRange(new[]
            {
                new ColumnHeader {
                    Text = "Diagnostic", Width = 300
                },
                new ColumnHeader {
                    Text = "Occurences", Width = 100
                },
            });

            _diagnosticsView.ItemActivate += (s, e) =>
            {
                if (_diagnosticsView.SelectedIndices.Count == 1)
                {
                    GoToNextRegexMatch(_regices[_diagnosticsView.SelectedIndices[0]]);
                }
            };

            _regices = diagnostics.Select(diagnostic => diagnostic.Regex).ToArray();
            foreach (var diagnostic in diagnostics)
            {
                _diagnosticsView.Items.Add(new ListViewItem(new[] { diagnostic.DisplayText, diagnostic.Matches.ToString() }));
            }

            _window.Load += (s, e) =>
            {
                _script.AutoWordSelection = false;
            };

            _window.Layout += (s, e) =>
            {
                _script.Width           = Math.Max(100, _window.Width - 500);
                _diagnosticsView.Height = Math.Max(100, _window.Height - 150);
            };

            var okButton = new Button {
                Text = "OK",
            };

            okButton.Size   = okButton.PreferredSize;
            okButton.Click += (s, e) =>
            {
                _window.DialogResult = DialogResult.OK;
                _window.Close();
            };

            var cancelButton = new Button {
                Text = "Cancel",
            };

            cancelButton.Size   = cancelButton.PreferredSize;
            cancelButton.Click += (s, e) =>
            {
                _window.DialogResult = DialogResult.Cancel;
                _window.Close();
            };

            var searchBox = new TextBox
            {
                AcceptsReturn = false,
                Width         = 200,
            };

            var searchButton = new Button {
                Text = "Find Next",
            };

            searchButton.Click += (s, e) =>
            {
                if (!string.IsNullOrEmpty(searchBox.Text))
                {
                    Regex searchRegex;
                    try
                    {
                        searchRegex = new Regex(searchBox.Text);
                    }
                    catch (RegexParseException)
                    {
                        return;
                    }

                    GoToNextRegexMatch(searchRegex);
                }
            };

            var buttonsFlowLayout = new FlowLayoutPanel
            {
                Dock          = DockStyle.Fill,
                FlowDirection = FlowDirection.LeftToRight,
            };

            buttonsFlowLayout.AddControls(okButton, cancelButton, searchBox, searchButton);
            _window.AddControls(buttonsFlowLayout, _diagnosticsView, _script);
        }
Exemple #3
0
        private static void Main(string[] args)
        {
            _watcher          = new FileSystemWatcher();
            _watcher.Created += OnWatchedFileEvent;
            _watcher.Renamed += OnWatchedFileEvent;
            _watcher.Deleted += OnWatchedFileEvent;

            var form = new Form();

            form.Text = Title;

            _archiveInput = new TextBox
            {
                PlaceholderText = "Input map...",
            };

            _openCloseArchiveButton = new Button
            {
                Text    = "Open archive",
                Enabled = false,
            };

            _saveAsButton = new Button
            {
                Text = "Save As...",
            };

            _saveAsButton.Size    = _saveAsButton.PreferredSize;
            _saveAsButton.Enabled = false;

            _autoDetectFilesToDecompileButton = new Button
            {
                Text = "Detect files to decompile",
            };

            _autoDetectFilesToDecompileButton.Size    = _autoDetectFilesToDecompileButton.PreferredSize;
            _autoDetectFilesToDecompileButton.Enabled = false;

            _filesToDecompileCheckBoxes = new[]
            {
                new MapFileCheckBox(MapFiles.Sounds, MapSounds.FileName),
                new MapFileCheckBox(MapFiles.Cameras, MapCameras.FileName),
                new MapFileCheckBox(MapFiles.Regions, MapRegions.FileName),
                new MapFileCheckBox(MapFiles.Triggers, MapSounds.FileName),
                new MapFileCheckBox(MapFiles.Units, MapUnits.FileName),
            };

            foreach (var checkBox in _filesToDecompileCheckBoxes)
            {
                checkBox.Size    = checkBox.PreferredSize;
                checkBox.Enabled = false;

                checkBox.CheckedChanged += (s, e) =>
                {
                    _saveAsButton.Enabled = _filesToDecompileCheckBoxes.Any(checkBox => checkBox.Checked);
                };
            }

            _archiveInput.TextChanged += OnArchiveInputTextChanged;

            _archiveInputBrowseButton = new Button
            {
                Text = "Browse",
            };

            _archiveInputBrowseButton.Size   = _archiveInputBrowseButton.PreferredSize;
            _archiveInputBrowseButton.Click += (s, e) =>
            {
                var openFileDialog = new OpenFileDialog
                {
                    CheckFileExists = false,
                };
                openFileDialog.Filter = string.Join('|', new[]
                {
                    "Warcraft III map|*.w3m;*.w3x",
                    "All files|*.*",
                });
                var openFileDialogResult = openFileDialog.ShowDialog();
                if (openFileDialogResult == DialogResult.OK)
                {
                    _archiveInput.Text = openFileDialog.FileName;
                }
            };

            _openCloseArchiveButton.Size   = _openCloseArchiveButton.PreferredSize;
            _openCloseArchiveButton.Click += OnClickOpenCloseMap;

            _saveAsButton.Click += (s, e) =>
            {
                var saveFileDialog = new SaveFileDialog
                {
                    OverwritePrompt = true,
                    CreatePrompt    = false,
                };

                var saveFileDialogResult = saveFileDialog.ShowDialog();
                if (saveFileDialogResult == DialogResult.OK)
                {
                    _progressBar.CustomText = "Starting...";
                    _progressBar.Value      = 0;

                    _openCloseArchiveButton.Enabled           = false;
                    _saveAsButton.Enabled                     = false;
                    _autoDetectFilesToDecompileButton.Enabled = false;
                    foreach (var checkBox in _filesToDecompileCheckBoxes)
                    {
                        checkBox.Enabled = false;
                    }

                    _progressBar.Visible = true;

                    _worker.RunWorkerAsync(saveFileDialog.FileName);
                }
            };

            _autoDetectFilesToDecompileButton.Click += (s, e) =>
            {
                var filesToDecompile = MapDecompiler.AutoDetectMapFilesToDecompile(_map);

                foreach (var checkBox in _filesToDecompileCheckBoxes)
                {
                    checkBox.Checked = filesToDecompile.HasFlag(checkBox.MapFile);
                }
            };

            _progressBar = new TextProgressBar
            {
                Dock       = DockStyle.Bottom,
                Style      = ProgressBarStyle.Continuous,
                VisualMode = TextProgressBar.ProgressBarDisplayMode.CustomText,
                Visible    = false,
            };

            _worker = new BackgroundWorker
            {
                WorkerReportsProgress      = true,
                WorkerSupportsCancellation = true,
            };

            _worker.DoWork             += DecompileMapBackgroundWork;
            _worker.ProgressChanged    += DecompileMapProgressChanged;
            _worker.RunWorkerCompleted += DecompileMapCompleted;

            // Initialize parser
            JassSyntaxFactory.ParseCompilationUnit(string.Empty);

            var flowLayout = new FlowLayoutPanel
            {
                Dock          = DockStyle.Fill,
                FlowDirection = FlowDirection.TopDown,
                WrapContents  = false,
            };

            var inputArchiveFlowLayout = new FlowLayoutPanel
            {
                FlowDirection = FlowDirection.LeftToRight,
            };

            var buttonsFlowLayout = new FlowLayoutPanel
            {
                FlowDirection = FlowDirection.LeftToRight,
            };

            var checkBoxesFlowLayout = new FlowLayoutPanel
            {
                FlowDirection = FlowDirection.TopDown,
                WrapContents  = false,
            };

            inputArchiveFlowLayout.AddControls(_archiveInput, _archiveInputBrowseButton, _openCloseArchiveButton);
            buttonsFlowLayout.AddControls(_saveAsButton, _autoDetectFilesToDecompileButton);
            checkBoxesFlowLayout.AddControls(_filesToDecompileCheckBoxes);
            checkBoxesFlowLayout.Size = checkBoxesFlowLayout.PreferredSize;

            flowLayout.AddControls(inputArchiveFlowLayout, buttonsFlowLayout, checkBoxesFlowLayout);

            form.AddControls(flowLayout, _progressBar);

            form.SizeChanged += (s, e) =>
            {
                var width = form.Width;
                _archiveInput.Width = (width > 360 ? 360 : width) - 10;

                inputArchiveFlowLayout.Size = inputArchiveFlowLayout.GetPreferredSize(new Size(width, 0));
                buttonsFlowLayout.Size      = buttonsFlowLayout.GetPreferredSize(new Size(width, 0));
                flowLayout.Height
                    = inputArchiveFlowLayout.Margin.Top + inputArchiveFlowLayout.Height + inputArchiveFlowLayout.Margin.Bottom
                      + buttonsFlowLayout.Margin.Top + buttonsFlowLayout.Height + buttonsFlowLayout.Margin.Bottom;
            };

            form.Size        = new Size(400, 400);
            form.MinimumSize = new Size(400, 300);

            form.FormClosing += (s, e) =>
            {
                _archive?.Dispose();
                _worker?.Dispose();
            };

            form.ShowDialog();
        }
Exemple #4
0
        private static void Main(string[] args)
        {
            _watcher          = new FileSystemWatcher();
            _watcher.Created += OnWatchedFileEvent;
            _watcher.Renamed += OnWatchedFileEvent;
            _watcher.Deleted += OnWatchedFileEvent;

            var form = new Form();

            form.Text = Title;

            _archiveInput = new TextBox
            {
                PlaceholderText = "Input map...",
            };

            _openCloseArchiveButton = new Button
            {
                Text    = "Open archive",
                Enabled = false,
            };

            _saveAsButton = new Button
            {
                Text = "Save As...",
            };

            _saveAsButton.Size    = _saveAsButton.PreferredSize;
            _saveAsButton.Enabled = false;

            _targetScriptLanguagesComboBox = new ComboBox
            {
                Enabled       = false,
                DropDownStyle = ComboBoxStyle.DropDownList,
                Width         = 120,
            };

            _targetScriptLanguagesComboBox.SelectedIndexChanged += (s, e) =>
            {
                _targetScriptLanguage = (ScriptLanguage?)_targetScriptLanguagesComboBox.SelectedItem;
                _saveAsButton.Enabled = _targetScriptLanguage.HasValue;
            };

            _targetScriptLanguagesComboBox.FormattingEnabled = true;
            _targetScriptLanguagesComboBox.Format           += (s, e) =>
            {
                if (e.ListItem is ScriptLanguage scriptLanguage)
                {
                    e.Value = scriptLanguage.ToString();
                }
            };

            _archiveInput.TextChanged += OnArchiveInputTextChanged;

            _archiveInputBrowseButton = new Button
            {
                Text = "Browse",
            };

            _archiveInputBrowseButton.Size   = _archiveInputBrowseButton.PreferredSize;
            _archiveInputBrowseButton.Click += (s, e) =>
            {
                var openFileDialog = new OpenFileDialog
                {
                    CheckFileExists = false,
                };
                openFileDialog.Filter = string.Join('|', new[]
                {
                    "Warcraft III map|*.w3m;*.w3x",
                    "All files|*.*",
                });
                var openFileDialogResult = openFileDialog.ShowDialog();
                if (openFileDialogResult == DialogResult.OK)
                {
                    _archiveInput.Text = openFileDialog.FileName;
                }
            };

            _openCloseArchiveButton.Size   = _openCloseArchiveButton.PreferredSize;
            _openCloseArchiveButton.Click += OnClickOpenCloseMap;

            _saveAsButton.Click += (s, e) =>
            {
                var saveFileDialog = new SaveFileDialog
                {
                    OverwritePrompt = true,
                    CreatePrompt    = false,
                };

                var saveFileDialogResult = saveFileDialog.ShowDialog();
                if (saveFileDialogResult == DialogResult.OK)
                {
                    _progressStepIndex = 0;

                    _progressBar.CustomText = _progressBarSteps[_progressStepIndex];
                    _progressBar.Value      = 0;

                    _openCloseArchiveButton.Enabled        = false;
                    _saveAsButton.Enabled                  = false;
                    _targetScriptLanguagesComboBox.Enabled = false;
                    _progressBar.Visible = true;

                    _worker.RunWorkerAsync(saveFileDialog.FileName);
                }
            };

            _progressBar = new TextProgressBar
            {
                Dock       = DockStyle.Bottom,
                Style      = ProgressBarStyle.Continuous,
                VisualMode = TextProgressBar.ProgressBarDisplayMode.CustomText,
                Visible    = false,
            };

            _worker = new BackgroundWorker
            {
                WorkerReportsProgress      = true,
                WorkerSupportsCancellation = false,
            };

            _worker.DoWork             += TranspileMapBackgroundWork;
            _worker.ProgressChanged    += TranspileMapProgressChanged;
            _worker.RunWorkerCompleted += TranspileMapCompleted;

            // Initialize parser
            JassSyntaxFactory.ParseCompilationUnit(string.Empty);

            var flowLayout = new FlowLayoutPanel
            {
                Dock          = DockStyle.Fill,
                FlowDirection = FlowDirection.TopDown,
            };

            var inputArchiveFlowLayout = new FlowLayoutPanel
            {
                FlowDirection = FlowDirection.LeftToRight,
            };

            var buttonsFlowLayout = new FlowLayoutPanel
            {
                FlowDirection = FlowDirection.LeftToRight,
            };

            var targetScriptLanguageLabel = new Label
            {
                Text      = "Transpile to",
                TextAlign = ContentAlignment.BottomRight,
            };

            inputArchiveFlowLayout.AddControls(_archiveInput, _archiveInputBrowseButton, _openCloseArchiveButton);
            buttonsFlowLayout.AddControls(_saveAsButton, targetScriptLanguageLabel, _targetScriptLanguagesComboBox);
            flowLayout.AddControls(inputArchiveFlowLayout, buttonsFlowLayout);

            form.AddControls(flowLayout, _progressBar);

            targetScriptLanguageLabel.Size = targetScriptLanguageLabel.PreferredSize;

            form.SizeChanged += (s, e) =>
            {
                var width = form.Width;
                _archiveInput.Width = (width > 360 ? 360 : width) - 10;

                inputArchiveFlowLayout.Size = inputArchiveFlowLayout.GetPreferredSize(new Size(width, 0));
                buttonsFlowLayout.Size      = buttonsFlowLayout.GetPreferredSize(new Size(width, 0));
                flowLayout.Height
                    = inputArchiveFlowLayout.Margin.Top + inputArchiveFlowLayout.Height + inputArchiveFlowLayout.Margin.Bottom
                      + buttonsFlowLayout.Margin.Top + buttonsFlowLayout.Height + buttonsFlowLayout.Margin.Bottom;
            };

            form.Size        = new Size(400, 300);
            form.MinimumSize = new Size(400, 200);

            form.FormClosing += (s, e) =>
            {
                _archive?.Dispose();
                _worker?.Dispose();
            };

            form.ShowDialog();
        }