summaryrefslogtreecommitdiff
path: root/include/vcl/roadmapwizard.hxx
blob: de70169fdbcc57639d8d5c63dadd77856f3b8463 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef INCLUDED_VCL_ROADMAPWIZARD_HXX
#define INCLUDED_VCL_ROADMAPWIZARD_HXX

#include <memory>
#include <vcl/dllapi.h>
#include <vcl/wizardmachine.hxx>

namespace vcl
{
    struct RoadmapWizardImpl;
    class RoadmapWizard;

    struct RoadmapWizardTypes
    {
    public:
        typedef sal_Int16                                   PathId;
        typedef ::std::vector< vcl::WizardTypes::WizardState >   WizardPath;
        typedef VclPtr<TabPage> (* RoadmapPageFactory)( RoadmapWizard& );
    };


    //= RoadmapWizard

    /** is - no, not a wizard for a roadmap, but the base class for wizards
        <em>supporting</em> a roadmap.

        The basic new concept introduced is a <em>path</em>:<br/>
        A <em>path</em> is a sequence of states, which are to be executed in a linear order.
        Elements in the path can be skipped, depending on choices the user makes.

        In the most simple wizards, you will have only one path consisting of <code>n</code> elements,
        which are to be visited successively.

        In a slightly more complex wizard, you will have one linear path, were certain
        steps might be skipped due to user input. For instance, the user may decide to not specify
        certain aspects of the to-be-created object (e.g. by unchecking a check box),
        and the wizard then will simply disable the step which corresponds to this step.

        In a yet more advanced wizards, you will have several paths of length <code>n1</code> and
        <code>n2</code>, which share at least the first <code>k</code> states (where <code>k</code>
        is at least 1), and an arbitrary number of other states.
    */
    class VCL_DLLPUBLIC RoadmapWizard : public vcl::OWizardMachine, public RoadmapWizardTypes
    {
    private:
        std::unique_ptr<RoadmapWizardImpl>  m_pImpl;

    public:
        RoadmapWizard(
            vcl::Window* _pParent
        );
        virtual ~RoadmapWizard( ) override;
        virtual void dispose() override;

        void            SetRoadmapHelpId( const OString& _rId );

        void            SetRoadmapInteractive( bool _bInteractive );

        void            InsertRoadmapItem(int nIndex, const OUString& rLabel, int nId, bool bEnabled);
        void            DeleteRoadmapItems();
        int             GetCurrentRoadmapItemID() const;
        void            SelectRoadmapItemByID(int nId);
        void            SetItemSelectHdl( const Link<LinkParamNone*,void>& _rHdl );

        // returns whether a given state is enabled
        bool            isStateEnabled( WizardState _nState ) const;

        // WizardDialog overridables
        virtual bool    canAdvance() const override;
        virtual void    updateTravelUI() override;

    protected:
        /** declares a valid path in the wizard

            The very first path which is declared is automatically activated.

            Note that all paths which are declared must have the very first state in
            common. Also note that due to a restriction of the very base class (WizardDialog),
            this common first state must be 0.

            You cannot declare new paths once the wizard started, so it's recommended that
            you do all declarations within your derivee's constructor.

            @see activatePath

            @param _nId
                the unique id you wish to give this path. This id can later on be used
                to refer to the path which you just declared
        */
        void    declarePath( PathId _nPathId, const WizardPath& _lWizardStates);

        /** provides basic information about a state

            The given display name is used in the default implementation of getStateDisplayName,
            and the given factory is used in the default implementation of createPage.
        */
        void    describeState( WizardState _nState, const OUString& _rStateDisplayName, RoadmapPageFactory _pPageFactory );

        /** activates a path which has previously been declared with <member>declarePath</member>

            You can only activate paths which share the first <code>k</code> states with the path
            which is previously active (if any), where <code>k</code> is the index of the
            current state within the current path.

            <example>
            Say you have paths, <code>(0,1,2,5)</code> and <code>(0,1,4,5)</code>. This means that after
            step <code>1</code>, you either continue with state <code>2</code> or state <code>4</code>,
            and after this, you finish in state <code>5</code>.<br/>
            Now if the first path is active, and your current state is <code>1</code>, then you can
            easily switch to the second path, since both paths start with <code>(0,1)</code>.<br/>
            However, if your current state is <code>2</code>, then you can not switch to the second
            path anymore.
            </example>

            @param _nPathId
                the id of the path. The path must have been declared (under this id) with
                <member>declarePath</member> before it can be activated.

            @param _bDecideForIt
                If <TRUE/>, the path will be completely activated, even if it is a conflicting path
                (i.e. there is another path which shares the first <code>k</code> states with
                the to-be-activated path.)<br/>
                If <FALSE/>, then the new path is checked for conflicts with other paths. If such
                conflicts exists, the path is not completely activated, but only up to the point
                where it does <em>not</em> conflict.<br/>
                With the paths in the example above, if you activate the second path (when both are
                already declared), then only steps <code>0</code> and <code>1</code> are activated,
                since they are common to both paths.
        */
        void    activatePath( PathId _nPathId, bool _bDecideForIt = false );

        /** determine the next state to travel from the given one

            This method (which is declared in OWizardMachine and overwritten here)
            ensures that traveling happens along the active path.

            @see activatePath
        */
        virtual WizardState     determineNextState( WizardState _nCurrentState ) const override;

        /** en- or disables a state

            In the wizard's roadmap, states to travel to can be freely chosen. To prevent
            users from selecting a state which is currently not available, you can declare this
            state as being disabled.

            A situation where you need this may be when you have a checkbox which, when checked
            by the user, enables a page with additional settings. As long as this checkbox is
            not checked, the respective state would be disabled.

            Note that in theory, you can declare multiple paths, instead of disabling states.
            For instance, if you have a path where one state can be potentially disabled, then
            you could declare a second path, which does not contain this state. However, the
            disadvantage is that then, not the complete path would be visible in the roadmap,
            but only all steps up to the point where the both paths diverge.<br/>
            Another disadvantage is that the number of needed paths grows exponentially with
            the number of states which can be potentially disabled.

            @see declarePath
        */
        void    enableState( WizardState _nState, bool _bEnable = true );

        /** returns true if and only if the given state is known in at least one declared path
        */
        bool    knowsState( WizardState _nState ) const;

        // OWizardMachine overriables
        virtual void            enterState( WizardState _nState ) override;

        /** returns a human readable name for a given state

            There is a default implementation for this method, which returns the display name
            as given in a call to describeState. If there is no description for the given state,
            this is worth an assertion in a non-product build, and then an empty string is
            returned.
        */
        virtual OUString  getStateDisplayName( WizardState _nState ) const;

        /** creates a page for a given state

            This member is inherited from OWizardMachine, and default-implemented in this class
            for all states which have been described using describeState.
        */
        virtual VclPtr<TabPage> createPage( WizardState _nState ) override;

        /** asks for a new label of the wizard page

         */
        void    updateRoadmapItemLabel( WizardState _nState );

    private:
        DECL_DLLPRIVATE_LINK( OnRoadmapItemSelected, LinkParamNone*, void );

        /** updates the roadmap control to show the given path, as far as possible
            (modulo conflicts with other paths)
        */
        VCL_DLLPRIVATE void implUpdateRoadmap( );

    private:
        VCL_DLLPRIVATE void impl_construct();
    };

    class VCL_DLLPUBLIC RoadmapWizardMachine : public vcl::WizardMachine, public RoadmapWizardTypes
    {
    private:
        std::unique_ptr<RoadmapWizardImpl>  m_pImpl;

    public:
        RoadmapWizardMachine(weld::Window* _pParent);
        virtual ~RoadmapWizardMachine( ) override;

        void            SetRoadmapHelpId( const OString& _rId );

        // returns whether a given state is enabled
        bool            isStateEnabled( WizardState _nState ) const;

        // WizardDialog overridables
        virtual bool    canAdvance() const override;
        virtual void    updateTravelUI() override;

    protected:
        /** declares a valid path in the wizard

            The very first path which is declared is automatically activated.

            Note that all paths which are declared must have the very first state in
            common. Also note that due to a restriction of the very base class (WizardDialog),
            this common first state must be 0.

            You cannot declare new paths once the wizard started, so it's recommended that
            you do all declarations within your derivee's constructor.

            @see activatePath

            @param _nId
                the unique id you wish to give this path. This id can later on be used
                to refer to the path which you just declared
        */
        void    declarePath( PathId _nPathId, const WizardPath& _lWizardStates);

        /** provides basic information about a state

            The given display name is used in the default implementation of getStateDisplayName,
            and the given factory is used in the default implementation of createPage.
        */
        void    describeState( WizardState _nState, const OUString& _rStateDisplayName, RoadmapPageFactory _pPageFactory );

        /** activates a path which has previously been declared with <member>declarePath</member>

            You can only activate paths which share the first <code>k</code> states with the path
            which is previously active (if any), where <code>k</code> is the index of the
            current state within the current path.

            <example>
            Say you have paths, <code>(0,1,2,5)</code> and <code>(0,1,4,5)</code>. This means that after
            step <code>1</code>, you either continue with state <code>2</code> or state <code>4</code>,
            and after this, you finish in state <code>5</code>.<br/>
            Now if the first path is active, and your current state is <code>1</code>, then you can
            easily switch to the second path, since both paths start with <code>(0,1)</code>.<br/>
            However, if your current state is <code>2</code>, then you can not switch to the second
            path anymore.
            </example>

            @param _nPathId
                the id of the path. The path must have been declared (under this id) with
                <member>declarePath</member> before it can be activated.

            @param _bDecideForIt
                If <TRUE/>, the path will be completely activated, even if it is a conflicting path
                (i.e. there is another path which shares the first <code>k</code> states with
                the to-be-activated path.)<br/>
                If <FALSE/>, then the new path is checked for conflicts with other paths. If such
                conflicts exists, the path is not completely activated, but only up to the point
                where it does <em>not</em> conflict.<br/>
                With the paths in the example above, if you activate the second path (when both are
                already declared), then only steps <code>0</code> and <code>1</code> are activated,
                since they are common to both paths.
        */
        void    activatePath( PathId _nPathId, bool _bDecideForIt = false );

        /** determine the next state to travel from the given one

            This method (which is declared in OWizardMachine and overwritten here)
            ensures that traveling happens along the active path.

            @see activatePath
        */
        virtual WizardState     determineNextState( WizardState _nCurrentState ) const override;

        /** en- or disables a state

            In the wizard's roadmap, states to travel to can be freely chosen. To prevent
            users from selecting a state which is currently not available, you can declare this
            state as being disabled.

            A situation where you need this may be when you have a checkbox which, when checked
            by the user, enables a page with additional settings. As long as this checkbox is
            not checked, the respective state would be disabled.

            Note that in theory, you can declare multiple paths, instead of disabling states.
            For instance, if you have a path where one state can be potentially disabled, then
            you could declare a second path, which does not contain this state. However, the
            disadvantage is that then, not the complete path would be visible in the roadmap,
            but only all steps up to the point where the both paths diverge.<br/>
            Another disadvantage is that the number of needed paths grows exponentially with
            the number of states which can be potentially disabled.

            @see declarePath
        */
        void    enableState( WizardState _nState, bool _bEnable = true );

        /** returns true if and only if the given state is known in at least one declared path
        */
        bool    knowsState( WizardState _nState ) const;

        // OWizardMachine overriables
        virtual void            enterState( WizardState _nState ) override;

        /** returns a human readable name for a given state

            There is a default implementation for this method, which returns the display name
            as given in a call to describeState. If there is no description for the given state,
            this is worth an assertion in a non-product build, and then an empty string is
            returned.
        */
        virtual OUString  getStateDisplayName( WizardState _nState ) const;

        /** asks for a new label of the wizard page

         */
        void    updateRoadmapItemLabel( WizardState _nState );

    private:
        DECL_DLLPRIVATE_LINK( OnRoadmapItemSelected, const OString&, bool );

        /** updates the roadmap control to show the given path, as far as possible
            (modulo conflicts with other paths)
        */
        VCL_DLLPRIVATE void implUpdateRoadmap( );
    };

} // namespace vcl


#endif // OOO_ INCLUDED_VCL_ROADMAPWIZARD_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */